我有以下代码:
var Test = function () {
};
Test.prototype.doSomething = function() {
return "done";
};
现在,我创建了一个Test
对象var t = new Test();
alert(t.doSomething()); // Correct alerts "done"
现在我为原型添加另一种方法:
Test.prototype.fly = function() { return "fly"; };
alert(t.fly()); // Correctly alerts "fly" (existing objects get "live udpated")
现在,我将原型指向一个空白对象:
Test.prototype = {};
alert(t.doSomething()); // Continues to alert "done", but why?
alert(t.fly()); // Continues to alert "fly", but why?
var t2 = new Test();
alert(t.doSomething()); // As expected, this does not work
当我向原型添加方法时,它会正确反映所有新对象和现有对象
当我通过<name>.prototype = {};
“清空”原型时,它只会“空白”新实例,而不是现有实例。为什么呢?
答案 0 :(得分:4)
这是一个类比:
var a = {foo : 'bar'};
var b = a; //the same object as a
var c = a;
var d = a;
a.apple = 'orange';
a = 1; //a === 1. b, c and d stay the same, pointing to the object with apple
我在这里做的是替换a
指向的内容,而不是对象本身。
当您添加fly
时,您正在修改所有实例共享的单个原型对象,即Test.prototype
当前指向的对象。
但是当您为Test.prototype
分配了空白对象时,您修改了Test.prototype
指向的内容。它不会修改现有实例指向的内容。但是从现在开始,任何新实例现在都将使用Test.prototype
上的新对象作为其原型对象。
如果您熟悉C,我宁愿将JS变量视为指针而不是引用。
答案 1 :(得分:0)
我正在完成上一个答案,如果您想在所有实例上反映您的更改,您必须正确更新原型。
Prototype属性是一个对象,您可以使用保留关键字“delete”删除一个属性。
如果你想删除'doSomething'属性:
delete Test.prototype.doSomething;
答案 2 :(得分:0)
考虑
function Foo(){}
Foo.prototype = {a:{"VMAddress":"@1234"}}
考虑到Foo.prototype.a对象具有VMAddress“@ 1234” 如果你现在创建对象,
var f1 = new Foo();
现在f1.a将指向同一个对象,即虚拟机地址为“@ 1234” 如果你看
f1.a === Foo.prototype.a ;//prints tue
如果您现在将原型更改为其他值,
Foo.prototype = {a:{"VMAddress":"@5678"}}
如果你现在创建对象,
var f2 = new Foo();
虽然
f2.a === Foo.prototype.a; //prints true because both point to same VM address @5678
但是
f1.a === f2.a; //prints false
为什么? 因为他们的虚拟机地址不同(一个是@ 1234,另一个是@ 5678),实际上他们是不同的对象
最终裁决 对象创建时的原型链决定了对象的原型是什么。