我是Javascript的新手并且对使用继承带来了一个问题
到目前为止,本文一直很有帮助(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#More_flexible_constructors),但我在Chrome调试器中观察到的行为似乎与我期望看到的不相符。
我有两个案例:
Base = function () {
this.value = 0;
};
Base.prototype.constructor = Base;
Derived = function () {
Base.call(this);
};
Derived.prototype = new Base();
Derived.prototype.constructor = Derived;
在调试器中我看到了:
完成作业后,我看到了这个
实例中的值已更改,但原型中的值未更改。这是预期的吗?
我不太明白的第二种方法是这一点(此处再次引用 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#More_flexible_constructors(请参阅第39页底部截断的代码;重新访问属性继承')
Base = function () {
};
Base.prototype.constructor = Base;
Base.prototype.value = 0;
// Derived as before...
和作业后
已添加值作为新属性。难道这不会改变原型中的价值吗?或者我是否明确需要通过原型访问该值 - 例如derived.value.prototype.value = 5
非常感谢有关此事的任何信息!
谢谢!
更新
感谢所有回复的人,事实证明这与我在适当的时候不使用Object.create有关。我将我的代码更新为:
在调试器中我得到了我的预期:
这看起来不错! :)
感谢@sixfingeredman和@Bergi的帮助!
答案 0 :(得分:2)
首先,如果不是主题,请删除此行:
Base.prototype.constructor = Base;
没有做任何有用的事情。
现在回答你的问题,是的,行为是预期的。想象一下,如果它更新了.prototype
。由于.prototype
在所有实例之间共享,因此所有实例都会看到更新。那肯定不是你想要的。
当你这样做时:
var derived = new Derived();
您创建了一个继承自Derived.prototype
。
当你这样做时:
derived.value = 1;
您直接为该新对象指定了值。
所以在分配之前,继承链看起来像这样:
derived Derived.prototype Base.prototype Object.prototype
+-----------+ +-----------+ +-----------+ +-----------+
| | | | | | | |
| |---------| value:0 |---------| |---------| |
| | | | | | | |
+-----------+ +-----------+ +-----------+ +-----------+
分配后,它看起来像这样:
derived Derived.prototype Base.prototype Object.prototype
+-----------+ +-----------+ +-----------+ +-----------+
| | | | | | | |
| value:1 |---------| value:0 |---------| |---------| |
| | | | | | | |
+-----------+ +-----------+ +-----------+ +-----------+
因此,在分配之前,如果您在value
对象上查找derived
,则无法找到它,因此它会跳转到Derived.prototype
,在那里找到它
但在作业完成后,value
会直接在derived
对象上找到。
用你的第二种方式,原型链将开始看起来像这样:
derived Derived.prototype Base.prototype Object.prototype
+-----------+ +-----------+ +-----------+ +-----------+
| | | | | | | |
| |---------| |---------| value:0 |---------| |
| | | | | | | |
+-----------+ +-----------+ +-----------+ +-----------+
因此,在value
上查找derived
时,它会在找到derived
属性之前从Derived.prototype
到Base.prototype
遍历到value
因此,假设您从Derived
构造函数创建了一堆对象。上面的草图会发生变化,因此您创建的每个对象都会指向Derived.prototype
。
derived_1
+-----------+
| |
| |
| |
+-----------+
\______
\
\
derived_2 Derived.prototype Base.prototype Object.prototype
+-----------+ +-----------+ +-----------+ +-----------+
| | | | | | | |
| |---------| |---------| value:0 |---------| |
| | | | | | | |
+-----------+ +-----------+ +-----------+ +-----------+
/
______/
derived_3 /
+-----------+
| |
| |
| |
+-----------+
现在您可以看到为什么不想更新原型。
如果我们执行了derived_1.value = 42
并且更新了Derived.prototype
对象,那么当您从value
和derived_2
查找derived_3
时,您就会' d获取您分配给derived_1
的值。
答案 1 :(得分:2)
已添加值作为新属性。难道这不会改变原型中的值吗?
不,这种行为是预料之中的。属性仅在" get"上继承,而不是在设置上继承。将值分配给对象 1 的属性后,将更改(或创建)该对象上的属性。
1:除了accessor property (setter function) on the prototype
或者我是否明确需要通过原型来访问该值 - 例如
derived.value.prototype.value = 5
要更改原型上的值,您需要在原型上分配它,是的。在你的情况下,那将是
Derived.prototype.value = 5;
或
Object.getPrototypeOf(derived).value = 5;
顺便说一下,请注意Base
上的属性(在Derived.prototype
构造函数中按实例创建)根本不存在 - 请参阅What is the reason to use the 'new' keyword at Derived.prototype = new Base。而不是Derived.prototype = new Base;
你应该使用
Derived.prototype = Object.create(Base.prototype);