javaScript之typeof、instanceof、Object.prototype.toString.call()的区别

351 阅读2分钟

typeof

  • 常用于判断基本数据类型
  • 返回的结果是该变量类型的字符串
  • typeof的返回值包括 'number' 'string' 'undefined' 'boolean' bigint symbol function object (不包含null)
// typeof的返回值是该属性类型的字符串
typeof 1 === 'number'
typeof '' === 'string'
typeof undefined === 'undefined'
typeof true === 'boolean'
typeof BigInt(1) === 'bigint'
typeof Symbol() === 'symbol'
typeof (function(){}) === 'function'
typeof null === 'object' 
//值得注意的是null的typeof结果是object 这是因为null表示一个空对象的引用,数据在底层二进制前三位为000就会被判定为object,而null的二进制表示每一位都为0,所以结果是'object'
//使用Object.prototype.toString.call()判断null类型
Object.prototype.toString.call(null) === '[object Null]'

instanceof

  • instanceof的返回值是true或false
  • instanceof的判断逻辑是基于原型链
  • 用于判断一个引用类型是否属于某构造函数
  • 可以通过继承关系判断一个实例是否属于它的父类型
/*
* 1.所有引用类型的值,都是构造函数Object的实例对象
*/
({}) instanceof Object           //true
[] instanceof Object             //true
(()=>{}) instanceof Object       //true
new Date() instanceof Object     //true

// 2.继承关系 构造继承和原型链继承
function Fn() { };
let f1 = new Fn(); //构造继承
let f2 = {};
f2.__proto__ = Fn.prototype; //原型链继承
f1 instanceof Fn                 //true
f2 instanceof Fn                 //true

//3.类和子类
class Person { }
class Student extends Person { }
console.log(new Student() instanceof Student);  //true
console.log(new Student() instanceof Person);   //true

手动实现instanceof

//手动实现 instanceof
let myInstanceof = (a, b) => {
      // 循环判断左边的隐式原型在不在右边构造函数的原型链上
      let L = a.__proto__;
      let R = b.prototype;
      while (true) {
        //沿着原型链一直找 找到则返回true,一直找到顶级原型对象Object.__proto__===null 返回false  
        if (L !== R) L = L.__proto__;
        if (L === R) return true;
        if (L === null) return false;
      }
  }

Object.prototype.toString.call()

  • toString是Object原型上面的方法,Array,Function等作为Object的子类基于toString方法实现了重写,以达到针对不同类型数据调用toString方法返回不同的隐式转换结果\
    "字符串".toString()         //'字符串'
    (100).toString()           //'100'
    (()=>{}).toString()        //'()=>{}'
    false.toString()           //'false'
    new Date().toString()      //'Mon Dec 27 2021 14:09:38 GMT+0800 (中国标准时间)'
  • Object.prototype.toString()方法内部会调用 [Symbol.toStringTag] 返回对象类型的默认字符串描述,"[object xx]" xx则对应[Symbol.toStringTag]的结果, Object.prototype.toString()最终结果为 "[object xx]"的字符串
// String 类型,tag为"String" 
Object.prototype.toString.call("");            // => "[object String]"
// Boolean 类型,tag为"Boolean" 
Object.prototype.toString.call(true);            // => "[object Boolean]"
// Number 类型,tag为"Number"
Object.prototype.toString.call(1);               // => "[object Number]"
// Array 类型,tag为"String"
Object.prototype.toString.call([]);              // => "[object Array]"
// Function 类型,tag 为"Function"
Object.prototype.toString.call(function(){});    // => "[object Function]"
// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error());     // => "[object Error]"
// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/);           // => "[object RegExp]"
// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date());      // => "[object Date]"
// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new class {});    // => "[object Object]"