js判断数据类型总结

209 阅读2分钟

前言:本篇文章将介绍typeof、instanceof、以及Object.prototype.toString.call方法如何判断数据类型,以及实现了一个简单的instanceof和call函数。欢迎在评论区指正并且提出建议!

typeof

typeof可以判断基本数据类型,但是不能判断引用数据类型(对象)

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object    
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object

instanceof

instanceof可以正确判断引用数据类型,原理是判断原型链上是否有右侧对象的原型。但是不能判断基本数据类型。

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

如果我们想让instanceof判断基本数据类型也是可以的!可以用包装类封装一层,如下。

image.png

被包裹的引用数据类型也能判断(毕竟会在原型链上找)

image.png

这里穿插一下instanceof的实现

function isObject(data) {
  const type = typeof data;
  // 注意,typeof null也是对象类型,所以先判断是否为null
  return data && (type === "object" || type === "function");
}
function myIntance(left, right) {
  //如果有一个不是
  if (!isObject(left) || !isObject(right)) {
    return false;
  }
  //取出右边对象的原型,进行判断
  if (left.__proto__ === right.prototype) return true;
  // 递归进行判断
  return myIntance(left.__proto__, right);
}

console.log(myIntance([], Array));  //true
console.log(myIntance([], Object));  //true
console.log(myIntance({}, Object));  //true
console.log(myIntance(() => {}, Function));  //true


Object.prototype.toString.call

也可以使用Object原型上的toString方法,通过call修改this指向来调用该方法,进而判断数据类型。

因为很多包装类以及Function,Array等类型都是Object的实例,重写了Object的toString方法。所以我们需要调用最原始的toString来判断类型

const a = Object.prototype.toString;
 
console.log(a.call(2));  //[object Number]
console.log(a.call(true)); //[object Boolean]
console.log(a.call('str'));  //[object String]
console.log(a.call([]));  //[object Array]
console.log(a.call(function(){})); //[object Function]
console.log(a.call({})); //[object Object]
console.log(a.call(undefined));  //[object Undefined]
console.log(a.call(null)); //[object Null]

这里附上call方法的实现~

function myCall(thisArg, ...args) {
  // 如果传入的是基本数据类型,就用包装类封装
  thisArg = typeof thisArg === "object" ? thisArg : Object(thisArg);

  // 获取this,也就是调用这个方法的函数
  const fn = this;

  // 使用隐式绑定,在thisArg上绑定fn并且调用,来改变this的指向
  const symbolFn = Symbol("fn"); //用Symbol防止fn重名覆盖
  thisArg[symbolFn] = fn;
  
  // 调用函数,获取返回值
  const res = thisArg[symbolFn](...args);
  //删除Symbol属性
  delete thisArg[symbolFn]; 
  //返回
  return res;
}

Function.prototype.call = myCall;

function foo(num1, num2) {
  console.log(this);
  console.log(this.name);
  console.log(num1 + num2);
}
foo.call({ name: "wjj" }, 10, 20);