快速注意:请不要在答案中解释javascript继承的基础知识。
这是一个简单的构造函数,其中有一些属性附加到它的原型成员。
function Foo() {
this.relationship = "Love";
};
Foo.prototype.name = "Natalie";
Foo.prototype.age = 22;
Foo.prototype.country = "France";
现在我们用Foo创建新对象并测试一些基础知识。一切都很酷。
var girl = new Foo();
girl.hasOwnProperty("relationship"); //=> true
girl.hasOwnProperty("name"); //=> false
girl.relationship; //=> "Love"
girl.name; //=> "Natalie", this comes from Foo.prototype
girl.__proto__ === Foo.prototype; //=> true
girl.__proto__.name === Foo.prototype.name; //=> true
girl.name === Foo.prototype.name; //=> true
如果我们更新Foo.prototype.name属性的值,girl.name将指向新值。
Foo.prototype.name = "Lucia";
girl.name; //=> "Lucia", this comes from Foo.prototype
当我们改变Foo.prototype并使其为null,未定义,空对象等时,会发生神秘的事情。
Foo.prototype = null;
如果我们的 girl 对象有一个隐藏的__ proto__
(ECMA [[Prototype]])链接到Foo.prototype,那么在制作Foo.prototype null 之后女孩应该没有机会获得名称属性,但确实如此!
girl.name; //=> "Lucia"
girl.age; //=> 22
girl.country; //=> "France"
现在如果我们用Foo创建另一个对象。它没有 name , age 和 country ,因为当然,Foo.prototype为null。
var new_girl = new Foo();
new_girl.name; //=> undefined
new_girl.age; //=> undefined
new_girl.country; //=> undefined
所以我的问题是在我们将Foo.prototype指定为 null 之后,前一个对象( girl )和他隐藏的__ proto__
链接如何记住这些属性吗
答案 0 :(得分:2)
它根本不是神秘的,它与继承无关 它与对象指针/引用有关。
var a = { name : "Bob", age : 32 };
var b = a;
b.name; // "Bob";
a.name = "Jim";
b.name; // "Jim";
a = null;
b.name; // "Jim";
发生了什么事?
a
和b
被赋予了指向同一对象的指针
当您更改对象的属性时,通过引用其中一个(如果您在a
或b
上更改它们无关紧要),则另一个引用也会看到变化。
你没有制作具有相同属性和值的新对象,你只是给它们同一个对象的地址,并且每次你问它们时它们都会查找属性。
然后重新分配a
。
您没有更改对象,而是将a
地址提供给其他地方
b
仍有地址。
所以现在想一想:
function Foo () { }
Foo.prototype = { name : "Bob", age : 32 };
var a = new Foo();
var b = new Foo();
a.__proto__ === Foo.prototype;
b.__proto__ === Foo.prototype;
Foo.prototype.age = 35;
a.age; // 35
b.age; // 35
// now we're replacing the `.prototype` reference with a brand new object
Foo.prototype = { name : "Sally", age : 16 };
a.__proto__ !== Foo.prototype;
b.__proto__ !== Foo.prototype;
a.name; // "Bob"
b.age; // 35
所有构造函数在后台都在说:
this.constructor = arguments.callee;
this.__proto__ = this.constructor.prototype;
因此,当您更改this.constructor.prototype
和this.__proto__
上引用的对象的属性时,将查找新值。
但是从一个引用中删除引用不会删除另一个引用的对象。
如果这是你想要的结果,那么你需要擦除原型的每个属性(无论你从哪里做 - 来自函数或来自任何实例)然后使{{无效1}}通过将其设置为空对象(null会在较小的浏览器上导致错误),因此将来的对象无法访问。