小姜哥的微信

修改构造函数原型——JavaScript中的对象(二)

今天先不写原型继承,先看一个误区:“改变构造函数的原型(prototype)将魔法般的(magically)更新新对象和已经存在的对象……”

这是完全错误的,不要相信解释JavaScript(包括任何事情)时使用了魔法(magic)这个单词的作者。

function C() {} //constructor
var x = new C();
C.prototype.prop = 2;
var y = new C();
alert(x.prop);
alert(y.prop);这段代码将alert "2" 和 "2",这似乎证实了上面引号中的定义,因为x对象在创建后增加了属性prop。魔法般的?其实不是,看下面的例子。

function C() {} //constructor
var x = new C();
C.prototype = {prop: 2};
var y = new C();
alert(x.prop);
alert(y.prop);这段代码将alert "undefined" 和 "2"。

在第一个例子中对象x和y均有属性prop。他们是隐藏在对象所引用的原型中(隐藏? 因为只有解析器可以访问它)。当访问prop属性的时候JavaScript无法在对象本身中找到,之后会搜索原型链,在原型链中找到并返回。这对于一个程序员来说是透明的。当你向原型中增加一个新属性的时候对象x是不改变的。当你访问prop属性的时候会在更新后的原型中找到它。

第二个例子中我们将原型改为一个新对象,而x依然使用旧的原型,但是y使用的是新原型,所以x和y不共享原型。很明显旧原型不存在prop属性。更糟糕的是,现在你丢失了唯一的访问点(无法访问旧原型了)。虽然创建对象的语法相同,但是他们是不同的。

另外,众所周知,每一个对象有一个constructor属性指向构造函数。但是像prop那样,constructor属性存在于原型中而不是对象本身。

重写原型的同时也重写了constructor属性,如下:

alert(x.constructor); // "function C() {}"
alert(y.constructor); // "function Object() { [native code] }"因此当你重写原型后constructor属性是不可信的,但是重写原型又是JavaScript中的重要技术。

译者:

本文讲述了JavaScript中重写原型后原型不一致的问题和constructor属性指向问题。动态修改原型对象不会在已有对象中生效。重写原型对象后constructor的指向将是不可信的,可以在重写原型后将constructor属性重新赋值。如

function C();

C.prototype = {};

C.prototype.constructor = C;

推荐文章

回到顶部