JS中的instanceof运算符

  js中的instanceof运算符

 MDN给出的解释是:

  instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

       看到这里我们就明白了instanceof是与原型和原型链有关系的,在弄懂instanceof之前我们就必须要了解什么是原型和原型链,关于原型和原型链详细的解释可以翻看我的另一篇博客彻底理解js的原型和原型链

 语法:

       object instanceof constructor 

    object         ——> 某个实例对象

    constructor ——>某个构造函数

   实例:

// 定义构造函数
function C(){}
function D(){}

//实例化对象 var o = new C(); o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype o instanceof D; // false,因为 D.prototype 不在 o 的原型链上 o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true C.prototype instanceof Object; // true,同上 C.prototype = {}; var o2 = new C(); o2 instanceof C; // true o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上. D.prototype = new C(); // 继承 var o3 = new D(); o3 instanceof D; // true o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上

  辨析instanceof和typeof:

  instanceof的功能类似于typeof,都是判断类型。对于值的类型,如string/number/boolean我们都可以通过typeof判断,但是typeof在判断引用类型时,返回值只有object/function,你不知道它到底是一个object对象,还是数组,还是new Number等等。听着还是有点模糊,那么我们通过一段代码来更好的理解typeof的判断类型是什么

   var a = 18;
    var b = 'smile';
    var c = true;
    var d = [];
    var e = {};
    function f() {

    }

    console.log(typeof (a));//number
    console.log(typeof (b));//string
    console.log(typeof (c));//boolean
    console.log(typeof (d));//object
    console.log(typeof (e));//object
    console.log(typeof (f));//function

 

  那么instanceof又是怎么判断的呢?

  我们先假设有一个函数A,A有一个实例化对象a,instanceof的判断规则是沿着a的__proto__这条线去找,同时沿着A的prototype这条线去找,如果两条线能找到同一个引用,即同一个对象,就返回true,如果找到终点还没有重合就返回false.同样,我们也将通过一段代码来理解instance的判断类型

   function A() {

    }
    var a = new A();
    var b = [];

    console.log(a instanceof A);//true
    console.log(A instanceof Function);//true
    console.log(b instanceof Array);//true
    console.log(a instanceof Array);//false

 

  扩展   

  其实对于类型的判断我们还可以使用constructor,至于constructor的原理在这里就不过多解释了,想了解的可以翻看我的另一篇博客JS的原型和原型链

    var a = 4;
    var arr = [];
    var obj = {};
    function fun(){};
    console.log(a.constructor === Number);//true
    console.log(arr.constructor === Array);//true
    console.log(obj.constructor === Object);//true
    console.log(fun.constructor === Function);//true

  虽然constructor既可以判断基本数据类型又可以判断引用类型,但是它还是存在很多弊端的。

  比如它会出现跨框架问题(instanceof也存在),理想情况(单框架)下, var arr = new Array(), arr 自然是Array的实例,检测结果当然准确。但具体应用中,如果使用多个框架(使用frame),浏览器中就会存在多个 window(Global)对象,每个 window 又都有自己的 Array 等一套构造函数,它们一一对应,却并不相等。解释起来很拗口,其实道理很简单:在中国你说家在首都,谁都知道指的是北京。在美国如果你也说家在首都,别人又会理所当然地觉得你在讲华盛顿。每个国家(框架、执行环境)都有自己的“首都(原型对象)”,但这个“首都”却指向不同的位置(对象)。“首都”因所属国家的不同而不同,Array因所属的window不同而不同。所以使用 instanceof 的时候要确保“同一框架”这个前提条件。此外constructor还可能因为实现对象继承时的疏忽导致错误结果,因为我们自己手动改变了默认的原型对象。

 

posted @ 2021-10-14 15:42  打遍天下吴敌手  阅读(7565)  评论(0编辑  收藏  举报