对象原型不“实时更新”

时间:2013-12-27 13:39:28

标签: javascript prototype

我有以下代码:

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
  1. 当我向原型添加方法时,它会正确反映所有新对象和现有对象

  2. 当我通过<name>.prototype = {};“清空”原型时,它只会“空白”新实例,而不是现有实例。为什么呢?

3 个答案:

答案 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),实际上他们是不同的对象

最终裁决 对象创建时的原型链决定了对象的原型是什么。