原型继承导致共享引用
Prototypal inheritance causes shared references
我想了解原型在 Javascript 中的作用和原因。在我以为我知道发生了什么之后,我偶然发现原型只是一个对象,不能像我想的那样被许多对象"shared"。让我举例说明:
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通常提倡的"objects inheriting from objects"概念,我认为我可以这样做:
var player = Object.create(SpritePrototype);
但事实证明这种方法是有缺陷的,因为非功能字段将是SpritePrototype中的那些,因为玩家的原型正是SpritePrototype。这意味着我无法从该原型创建更多对象,否则非函数字段将全部混淆。
那么 Object.create 的意义何在,更重要的是,实现我想要做的事情的正确方法是什么?也就是说,如何让 "player" 获取字段的副本并从其原型继承函数?
再次重申,我对按预期方式做事很感兴趣。我总是可以手动模拟继承或完全跳过它。我的问题的重点是了解原型以及它们如何以及何时有用,尤其是在我的具体情况下。
您的问题是,您根据面向对象设计定义了 "static" 成员。原型部分中的所有内容都在对象之间共享。函数实际上并没有被复制到新创建的对象,但它是用适当的 "this".
调用的
你应该像这样在构造函数中初始化你的变量
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
属性 原型上的值最初是共享的,但当实例上的 属性 被写入(分配)到时停止共享。在那一刻,该实例获得了它自己的 属性 版本。所以说这个值是 "shared" 并不完全正确。它仅在实例上的 属性 分配给的时间点之前共享。
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
的实例。
我想了解原型在 Javascript 中的作用和原因。在我以为我知道发生了什么之后,我偶然发现原型只是一个对象,不能像我想的那样被许多对象"shared"。让我举例说明:
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通常提倡的"objects inheriting from objects"概念,我认为我可以这样做:
var player = Object.create(SpritePrototype);
但事实证明这种方法是有缺陷的,因为非功能字段将是SpritePrototype中的那些,因为玩家的原型正是SpritePrototype。这意味着我无法从该原型创建更多对象,否则非函数字段将全部混淆。
那么 Object.create 的意义何在,更重要的是,实现我想要做的事情的正确方法是什么?也就是说,如何让 "player" 获取字段的副本并从其原型继承函数?
再次重申,我对按预期方式做事很感兴趣。我总是可以手动模拟继承或完全跳过它。我的问题的重点是了解原型以及它们如何以及何时有用,尤其是在我的具体情况下。
您的问题是,您根据面向对象设计定义了 "static" 成员。原型部分中的所有内容都在对象之间共享。函数实际上并没有被复制到新创建的对象,但它是用适当的 "this".
调用的你应该像这样在构造函数中初始化你的变量
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
属性 原型上的值最初是共享的,但当实例上的 属性 被写入(分配)到时停止共享。在那一刻,该实例获得了它自己的 属性 版本。所以说这个值是 "shared" 并不完全正确。它仅在实例上的 属性 分配给的时间点之前共享。
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
的实例。