`

JS的instanceof方法

 
阅读更多

今天突然想起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

 

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

分享到:
评论

相关推荐

    JS中typeof与instanceof的区别

    JS 中 typeof 与 instanceof 的区别 在 JavaScript 中,typeof 和 instanceof 是两个常用的运算符,用来判断一个变量是否为空,或者是什么类型的。但是,这两个运算符之间还是有区别的。 typeof 运算符是一个一元...

    JS:typeof instanceof constructor prototype区别

    本文将深入探讨四种常用的方法来识别和判断JavaScript中的数据类型:`typeof`、`instanceof`、`constructor`以及`prototype`。 ### 1. `typeof` `typeof`操作符是最常见的类型检测方式之一,它返回一个表示未经计算...

    instanceof.js ES5的instanceof手写实现

    ES5的instanceof手写实现

    JavaScript instanceof 的使用方法示例介绍

    `instanceof` 是 JavaScript 中的一个操作符,用于判断一个对象是否是某个构造函数的实例,或者是否属于特定的原型链。这个操作符在处理复杂的对象类型和继承关系时特别有用,因为 `typeof` 运算符在面对对象时只能...

    javascript instanceof 与typeof使用说明

    typeof用以获取一个变量的类型,typeof一般只能返回如下几个结果... 如果我们希望获取一个对象是否是数组,或判断某个变量是否是某个对象的实例则要选择使用instanceof。instanceof用于判断一个变量是否某个对象的实例

    【JavaScript源代码】JavaScript 手动实现instanceof的方法.docx

    在JavaScript中,每个对象都有一个`__proto__`属性(在ES6中推荐使用`Object.getPrototypeOf`方法),这个属性指向创建该对象的构造函数的`prototype`。当调用`new`操作符创建一个新实例时,这个实例的`__proto__`就...

    JavaScript的instanceof有bug?

    在JavaScript中,`instanceof`操作符用于检测一个对象是否属于某个类的实例。这个操作符在日常开发中被广泛使用,但有时它可能会表现出一些意外的行为,这可能被误认为是“bug”。本文将深入探讨`instanceof`的工作...

    理解Javascript_07_理解instanceof实现原理

    `instanceof`是JavaScript中一个重要的操作符,用于检测一个对象是否属于某个构造函数的实例。这个操作符的实现原理涉及到原型链(prototype chain)的概念,这是JavaScript中面向对象编程的基础之一。 首先,我们...

    前端面试题之baseJS-instanceof.zip

    "baseJS-instanceof.zip"这个压缩包文件显然聚焦于JavaScript的基础知识,特别是`instanceof`操作符的使用。在这里,我们将深入探讨`instanceof`在JavaScript中的工作原理、相关知识点以及在实际编程中的应用。 `...

    instanceof 和 prototype 关系

    在JavaScript中,`instanceof`和`prototype`是两个非常重要的概念,它们涉及到对象的类型检测和继承机制。本文将深入探讨这两个关键字的关系及其在实际编程中的应用。 首先,我们来理解`instanceof`操作符。`...

    js中的instanceof操作符1

    `instanceof`是JavaScript中的一个操作符,用于检查一个对象是否是特定构造函数的实例,或者更具体地说,是检查该对象的原型链上是否存在指定构造函数的`prototype`。这个操作符对于理解和处理对象继承关系非常关键...

    详解JavaScript中typeof与instanceof用法

    在JavaScript中,typeof和instanceof是常用的两种检测数据类型的方式,它们各自有其适用的场景和特点。 ### typeof typeof 是一个一元运算符,它用于返回变量或表达式的类型。当使用typeof运算符时,它通常会返回...

    JavaScript中instanceof运算符的用法总结

    使用方法:result = object instanceof class其中result是必选项。任意变量。object是必选项。任意对象表达式。class是必选项。任意已定义的对象类。 说明如果 object 是 class 的一个实例,则 instanceof 运算符...

    JavaScript中instanceof运算符的使用示例

    JavaScript中的instanceof运算符是面向对象编程中非常重要的一个概念,它用于检测一个实例对象的原型链上是否包含某个构造函数的原型。instanceof运算符的使用有助于理解JavaScript中的原型继承机制。 在JavaScript...

    javascript instanceof,typeof的区别

    在JavaScript中,`typeof` 和 `instanceof` 都是用来检查变量类型的,但它们之间有着本质的区别。 `typeof` 是一个操作符,它返回一个表示变量类型的字符串。它主要用于基本数据类型的判断,例如: - number - ...

    js代码-实现一个 instanceof

    在JavaScript中,`instanceof` 是一个非常常用的运算符,用于判断一个对象是否属于某个类(构造函数)的实例。这个运算符可以帮助我们检查对象的原型链,从而确定对象的类型。下面我们将深入探讨 `instanceof` 的...

    js代码-instanceof的实现

    JavaScript中的`instanceof`操作符是用来检测一个对象是否属于某个构造函数的实例。它在JavaScript的面向对象编程中扮演着重要角色,帮助开发者判断对象的类型。本文将深入探讨`instanceof`的工作原理,以及如何在...

    理解Javascriptinstanceof实现原理

    ### 理解JavaScript `instanceof` 实现原理 在JavaScript中,`instanceof` 运算符是一种常用的类型检测手段,它可以帮助我们判断一个对象是否为某个构造函数的实例。本文将深入探讨`instanceof` 的工作原理,并通过...

Global site tag (gtag.js) - Google Analytics