今天突然想起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:
- Let lref be the result of evaluating RelationalExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating ShiftExpression.
- Let rval be GetValue(rref).
- If Type(rval) is not Object, throw a TypeError exception.
- If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
- 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:
- If V is not an object, return false.
- Let O be the result of calling the [[Get]] internal method of F with property name
"prototype"
. - If Type(O) is not Object, throw a TypeError exception.
-
Repeat
- Let V be the value of the [[Prototype]] internal property of V.
- If V is
null
, return false. - 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 的区别 在 JavaScript 中,typeof 和 instanceof 是两个常用的运算符,用来判断一个变量是否为空,或者是什么类型的。但是,这两个运算符之间还是有区别的。 typeof 运算符是一个一元...
本文将深入探讨四种常用的方法来识别和判断JavaScript中的数据类型:`typeof`、`instanceof`、`constructor`以及`prototype`。 ### 1. `typeof` `typeof`操作符是最常见的类型检测方式之一,它返回一个表示未经计算...
ES5的instanceof手写实现
`instanceof` 是 JavaScript 中的一个操作符,用于判断一个对象是否是某个构造函数的实例,或者是否属于特定的原型链。这个操作符在处理复杂的对象类型和继承关系时特别有用,因为 `typeof` 运算符在面对对象时只能...
typeof用以获取一个变量的类型,typeof一般只能返回如下几个结果... 如果我们希望获取一个对象是否是数组,或判断某个变量是否是某个对象的实例则要选择使用instanceof。instanceof用于判断一个变量是否某个对象的实例
在JavaScript中,每个对象都有一个`__proto__`属性(在ES6中推荐使用`Object.getPrototypeOf`方法),这个属性指向创建该对象的构造函数的`prototype`。当调用`new`操作符创建一个新实例时,这个实例的`__proto__`就...
在JavaScript中,`instanceof`操作符用于检测一个对象是否属于某个类的实例。这个操作符在日常开发中被广泛使用,但有时它可能会表现出一些意外的行为,这可能被误认为是“bug”。本文将深入探讨`instanceof`的工作...
`instanceof`是JavaScript中一个重要的操作符,用于检测一个对象是否属于某个构造函数的实例。这个操作符的实现原理涉及到原型链(prototype chain)的概念,这是JavaScript中面向对象编程的基础之一。 首先,我们...
"baseJS-instanceof.zip"这个压缩包文件显然聚焦于JavaScript的基础知识,特别是`instanceof`操作符的使用。在这里,我们将深入探讨`instanceof`在JavaScript中的工作原理、相关知识点以及在实际编程中的应用。 `...
在JavaScript中,`instanceof`和`prototype`是两个非常重要的概念,它们涉及到对象的类型检测和继承机制。本文将深入探讨这两个关键字的关系及其在实际编程中的应用。 首先,我们来理解`instanceof`操作符。`...
`instanceof`是JavaScript中的一个操作符,用于检查一个对象是否是特定构造函数的实例,或者更具体地说,是检查该对象的原型链上是否存在指定构造函数的`prototype`。这个操作符对于理解和处理对象继承关系非常关键...
在JavaScript中,typeof和instanceof是常用的两种检测数据类型的方式,它们各自有其适用的场景和特点。 ### typeof typeof 是一个一元运算符,它用于返回变量或表达式的类型。当使用typeof运算符时,它通常会返回...
使用方法:result = object instanceof class其中result是必选项。任意变量。object是必选项。任意对象表达式。class是必选项。任意已定义的对象类。 说明如果 object 是 class 的一个实例,则 instanceof 运算符...
JavaScript中的instanceof运算符是面向对象编程中非常重要的一个概念,它用于检测一个实例对象的原型链上是否包含某个构造函数的原型。instanceof运算符的使用有助于理解JavaScript中的原型继承机制。 在JavaScript...
在JavaScript中,`typeof` 和 `instanceof` 都是用来检查变量类型的,但它们之间有着本质的区别。 `typeof` 是一个操作符,它返回一个表示变量类型的字符串。它主要用于基本数据类型的判断,例如: - number - ...
在JavaScript中,`instanceof` 是一个非常常用的运算符,用于判断一个对象是否属于某个类(构造函数)的实例。这个运算符可以帮助我们检查对象的原型链,从而确定对象的类型。下面我们将深入探讨 `instanceof` 的...
JavaScript中的`instanceof`操作符是用来检测一个对象是否属于某个构造函数的实例。它在JavaScript的面向对象编程中扮演着重要角色,帮助开发者判断对象的类型。本文将深入探讨`instanceof`的工作原理,以及如何在...
### 理解JavaScript `instanceof` 实现原理 在JavaScript中,`instanceof` 运算符是一种常用的类型检测手段,它可以帮助我们判断一个对象是否为某个构造函数的实例。本文将深入探讨`instanceof` 的工作原理,并通过...