原型继承导致共享引用

时间:2015-08-08 09:51:40

标签: javascript inheritance prototype prototypal-inheritance

我想了解原型在Javascript中的用途和原因。在我以为我知道发生了什么之后,我偶然发现原型只是一个物体而且不能像我想象的那样被许多物体“共享”。让我详细说明一下:

var SpritePrototype = {
    img: null,
    pos_x: 0,
    pos_y: 0,

    draw: function(context2d) {
        /*do stuff with the canvas
          using "this" to refer to 
          the object this method is 
          being called on*/
    },
    //Some more member functions...
}

从“通常用原型友好的Javascript提倡的对象继承的对象”的概念,我想我可以做到:

var player = Object.create(SpritePrototype);

但事实证明这种方法存在缺陷,因为非函数字段将来自SpritePrototype,因为玩家的原型恰好是SpritePrototype。这意味着我无法从该原型创建更多对象,或者非功能字段会混淆。

那么Object.create中的重点是什么,更重要的是,实现我想要做的事情的正确方法是什么?也就是说,如何让“播放器”获取字段的副本并从其原型继承功能?

同样,我有兴趣以他们想要的方式做事。我总是可以手工模拟继承或完全跳过它。我的问题是要了解原型以及它们如何以及何时有用,特别是在我的特定情况下。

2 个答案:

答案 0 :(得分:3)

原型上的属性值最初是共享的,但在写入(分配)实例上的该属性时停止共享。在那一刻,实例获得了自己的属性版本。所以说价值是“共享”并不完全正确。它仅在实例的属性分配到的时间点共享。

var SpritePrototype = {
    img: 'img1'
};
var sprite1 = Object.create(SpritePrototype);
var sprite2 = Object.create(SpritePrototype);

sprite1.img = 'img2';            // does NOT affect prototype or sprite2
console.log(sprite2.img);

< "img1"

引用img时,其值取自原型。但是,当img 写入时,会在实例上创建一个新属性来保存新值,并从此开始使用。

更改原型属性值的唯一方法是明确地这样做:

SpritePrototype.img = 'img3';

这将为所有尚未定义自己的img本地版本的实例更改img

答案 1 :(得分:1)

你的问题是,你已经定义了&#34;静态&#34;面向对象设计的成员。 protoype部分中的所有内容都在对象之间共享。函数实际上没有被复制到新创建的对象,但它被正确调用&#34;这个&#34;。

您应该在构造函数中初始化变量,例如

function Sprite(...) {
    this.img = null;
    ...
}

然后对于子类型,你应该使用Object.create创建一个原型来继承它的方法,所以

Player.prototype = Object.create(Sprite.prototype);

最后,您可以调用父构造函数来初始化变量

function Player(...) {
    Sprite.call(this, ...);
}

PS。构造函数应该在Player.prototype分配之前。

PPS。有关详细信息,请参阅此https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

相关问题