问题描述
我想了解原型在Java脚本中的作用以及为什么。 在以为自己知道发生了什么之后,我迷上了一个事实,那就是原型只是一个对象,不能像我所想的那样被许多对象“共享”。 让我举例说明:
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的意义何在?更重要的是,实现我想要做的事情的正确方法是什么? 也就是说,如何使“玩家”获得字段的副本并从其原型继承功能?
同样,我对按预期方式进行操作感兴趣。 我总是可以手动模拟继承,也可以完全跳过继承。 我的问题的重点是了解原型以及原型的使用方式和时间,特别是在我的特定情况下。
1楼
原型上的属性值最初是共享的,但是在实例上的属性值被写入(分配)后停止共享。 那时,实例将获得其自己的属性版本。 因此,说该值是“共享的”并不完全正确。 仅在实例属性分配到的时间点之前共享。
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
。
2楼
您的问题是,已根据面向对象的设计定义了“静态”成员。 原型部分中的所有内容在对象之间共享。 函数实际上并不会复制到新创建的对象,但是会使用适当的“ this”进行调用。
您应该在构造函数中初始化变量,如下所示
function Sprite(...) {
this.img = null;
...
}
然后对于子类型,您应该使用Object.create创建一个原型来继承其方法,因此
Player.prototype = Object.create(Sprite.prototype);
最后,您可以调用父构造函数来初始化变量
function Player(...) {
Sprite.call(this, ...);
}
PS。 构造函数应在Player.prototype分配之前。
PPS。 有关更多信息,请参见