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

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

最新文章

  1. [转] C++的STL库,vector sort排序时间复杂度 及常见容器比较
  2. 页面间(窗口间)的取值赋值及获取iframe下的window对象
  3. Spring中Quartz的最精简的配置
  4. objective-c底层: runtime机制
  5. bitmap size exceeds VM budget
  6. UVA 11478 Halum(用bellman-ford解差分约束)
  7. XML节点处理
  8. 选中excel中的对象
  9. C#集合之Hashtable
  10. oracle 存储过程 动态sql语句
  11. ZCTF-Restaurant-Pwn500
  12. brutal是什么意思_brutal在线翻译_英语_读音_用法_例句_海词词典
  13. Codeforces 490F. Treeland Tour 暴力+LIS
  14. Visual Studio 2015 & C#6.0 试用报告,持续更新。
  15. 一行一行分析JQ源码学习笔记-06
  16. Flask入门之自定义过滤器(匹配器)
  17. uboot - the bootloader of linux
  18. 2.SpringBoot HelloWorld详解
  19. [工具] Sublime Text 使用指南
  20. JavaScript学习笔记(七)—— 再说函数

热门文章

  1. 十分钟理解Java中的动态代理
  2. Delphi使用ADO连接网络数据库,断网后重连问题
  3. Docker 使用指南 (五)—— Dockerfile 详解
  4. jquery背景backgroundPosition插件
  5. centos6.8上安装paramiko
  6. ListView之EmptyView
  7. rest_framework之版本详解 04
  8. postgresql----数据库表约束----NOT NULL,DEFAULT,CHECK
  9. 让ASP.NET OutputCache使用http.sys kernel-mode cache
  10. SQL---->mySQl卸载for mac