function New(f){
return function(){
var o = {'__proto__': f.prototype};
f.apply(o, arguments);
return o;
}
}
function Person(name, age){
this.name = name;
this.age = age;
}
var p = New(Person)('xl', 24);

在一段javascript基础学习视频中,老师大胆想象了一下new方法创造实例对象的原理。

其中一个关键点,让对象的__proto__属性指向任何一个构造函数:{'__proto__': f.prototype}

这个我就蛮好奇的,直接这样,然后以下两段都成立了。

p instanceof Person   // true
p.constructor === Person // true

以上说明,这个隐藏的属性__proto__的指向一旦建立,那么p实例的constructor就自动指向了Person构造器(此理解是错的)。

夯实JavaScript基础之prototype, __proto__, instanceof-LMLPHP

2018-05-03:今天继续了解原型链时,发现我这里理解错了。其实p实例没有生成指向Person构造器的constructor属性,因为测试发现p.hasOwnProperty('constructor')结果是false。发现p.constructor有值,并指向Person,是因为p在自己上面找不到constructor时,沿着原型找到了Person原型的constructor属性,所以下图才是对的。

夯实JavaScript基础之prototype, __proto__, instanceof-LMLPHP

但是我还是好奇为什么。

之前我一直以为instanceof 是否成立还和constructor有关系。

而实际上是,{'__proto__': f.prototype}这个直接的导致了constructor关系(上图绿线)的建立。当我试图把constructor的两个关系重新指向时,

p.constructor = {other: 1};
Person.prototype.constructor = {other: 2}; p instanceof Person // true

p仍然是Person的实例,所以instanceof和constructor无关。而当我试图改变Person的prototype的指向之后,终于变了

Person.prototype = {other: 3}

p instanceof Person   // false

另外我尝试了一下,在改变Person.prototype指向之前,让其他任何函数的prototype都指向Person.prototype,则

function Person2(){}
Person2.prototype = Person.prototype p instanceof Person // true
p instanceof Person2 // true

p可以是多个构造函数的实例。

试验之后的结论是:

instanceof 与constructor属性无必然关系,只要对象的隐藏属性__proto__指向任何构造器的prototype属性,那么对象都会是该构造器的实例;对象也可以是多个构造器的实例。

修改:

结论改为

instanceof 与constructor属性无必然关系,只要对象的隐藏属性__proto__,或者对象的__proto__的__proto__,或者对象的__proto__的__proto__的__proto__..........指向任何构造器的prototype属性,那么对象都会是该构造器的实例;对象也可以是多个构造器的实例。

05-11 22:41