zoukankan      html  css  js  c++  java
  • JS的 instanceof 方法

    http://www.cnblogs.com/jasonxuli/p/6769282.html

    这是 2014-12-10 发在 iteye 上的文章

    今天突然想起js的原型继承模型和相关的prototype,constructor,觉得有点模糊,就写了个例子:

    var log = console.log;
    
    function A(){
        this.value = 1;
    }
    var a = new A();
    log('a.value = ', a.value);  // a.value =  1
    log('a instanceof A: ', a instanceof A);  // a instanceof A: true
    
    function B(){
        this.value = 2;
    }
    var b = new B();
    
    A.prototype = b;
    var aa = new A();
    log(aa.constructor == b.constructor); // true
    log('a.value = ', a.value);   // a.value =  1
    log('b.value = ', b.value);   // b.value =  2
    log('aa.value = ', aa.value);  // aa.value =  1
    
    log('a instanceof A: ', a instanceof A); // a instanceof A:  false
    log('a instanceof B: ', a instanceof B); // a instanceof B:  false 

    其他的都没问题,最后两行突然有点让我恍惚:

    为什么在A继承了B之后,a就不是A的实例了呢?

    于是就去查instanceof的文档,ECMA 262 5.1版:

    11.8.6The instanceof operator

    The production RelationalExpression : RelationalExpression instanceof ShiftExpression is evaluated as follows:

    1. Let lref be the result of evaluating RelationalExpression.
    2. Let lval be GetValue(lref).
    3. Let rref be the result of evaluating ShiftExpression.
    4. Let rval be GetValue(rref).
    5. If Type(rval) is not Object, throw a TypeError exception.
    6. If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
    7. Return the result of calling the [[HasInstance]] internal method of rval with argument lval.

    2, 4 条提到的GetValue又是一个坑,暂且不管,去看6, 7提到的内部方法[[HasInstance]]:

    15.3.5.3[[HasInstance]] (V)

    Assume F is a Function object.

    When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

    1. If V is not an object, return false.
    2. Let O be the result of calling the [[Get]] internal method of F with property name "prototype".
    3. If Type(O) is not Object, throw a TypeError exception.
    4. Repeat
      1. Let V be the value of the [[Prototype]] internal property of V.
      2. If V is null, return false.
      3. If O and V refer to the same object, return true.

     这一条大概等同于下面的逻辑:

    F为instanceof表达式的右值,也就是constructor;V是左值,也就是instance;

    HasInstance(V){
        if(typeof(V) != 'object')
            return false;
    
        var O = F.get('prototype'); // get 为内部方法
        if(typeof(O) != Object)
            throw new TypeError();
    
        while(1){ // 循环实例V的原型链
            V = V.__proto__; // 获取实例V的内部属性prototype,可以用Object.getPrototypeOf(V)获取
            if(V == null) // Object.prototype.__proto__ 为null,这也是最终的跳出语句
                return false;
    
            if(O === V)
                return true;
        }
    }
    
    F.HasInstance(V);

    查了文档,算是搞明白了:

    比较时使用的是实例的内部属性__proto__和构造函数的prototype,而实例内部属性__proto__只在被初始化的时候被设置为构造函数的prototype,因此

    A.prototype = b; // A 继承了 B

      而a的内部的__proto__还是A{},也就是a记得自己的亲爹是A{},但是现在的A认B做父了,所以a不承认是A的直系了。

      a instanceof A; // false

      a instanceof B; // false

    有点儿刻舟求剑的感觉不?!

  • 相关阅读:
    HarmonyOS Java UI之AdaptiveBoxLayout布局示例
    【鸿蒙开发板试用报告】OneNet平台+开发板实时监控温湿度(一)
    安装了瑞友天翼4.0后出现了远程桌面无法连接的问题
    CISVC.EXE的资源占用
    Delphi如何在窗体标题栏添加按钮
    Delphi中捕捉窗体的最小化、最大化、还原消息
    打印机任务无法删除
    Delphi创建一个虚幻的层窗口(Win2000/XP)
    工资年结时提示“上年数据已经结转”
    Delphi中如何控制其他程序窗体上的窗口控件
  • 原文地址:https://www.cnblogs.com/jasonxuli/p/6769282.html
Copyright © 2011-2022 走看看