在 JavaScript 中使用纯原型方法时如何处理对象属性
我是一位经验丰富的程序员,第一次学习 JavaScript,是使用 Douglas Crockford 的《Javascript:The Good Parts》一书。在其中,他建议使用“纯原型”方法来继承,使用这个函数:
if (typeof Object.create !== 'function') {
Object.create = function(o) {
var F = function () {};
F.prototype = o;
return new F();
};
}
我遇到的问题是,当一个对象具有一个对象而不是简单类型的属性时,创建一个新对象会继承父对象的实例该对象,而不是创建一个新对象。例如:
var aBody = {
arms : 2,
legs : 2
};
var person = {
name : 'Jeff',
body : Object.create(aBody)
};
document.writeln('Person '+person.name+' has '+person.body.arms+' arms and '+person.body.legs+' legs.');
var cat = Object.create(person);
cat.name = 'Bob';
cat.body.arms = 0;
cat.body.legs = 0;
document.writeln('Cat '+cat.name+' has '+cat.body.arms+' arms and '+cat.body.legs+' legs.');
document.writeln('Now person '+person.name+' has '+person.body.arms+' arms and '+person.body.legs+' legs.');
这有输出:
Person Jeff has 2 arms and 2 legs.
Cat Bob has 0 arms and 0 legs.
Now person Jeff has 0 arms and 0 legs.
我得到了简单“name”属性的预期行为,但没有得到“body”的预期行为。我想我明白了——因为 JavaScript 是通过引用复制的,所以不会生成 aBody 的新实例。每次我使用例如 cat.body = Object.create(aBody)
从 person
创建对象时,我都可以手动执行此操作,但我还没有找到一种简洁的方法将其滚动到原始对象定义中(此处为 person
)。
我真的很感激你能提供的任何指导,因为我正在努力学习编写漂亮、清晰、可靠的 JS 代码。使用“纯原型”方法的人们是否有一种聪明的技术来处理这个问题?
I'm an experienced coder learning JavaScript for the first time, using Douglas Crockford's "Javascript: The Good Parts" book. In it, he recommends using a 'purely prototypal' approach to inheritance, using this function:
if (typeof Object.create !== 'function') {
Object.create = function(o) {
var F = function () {};
F.prototype = o;
return new F();
};
}
The problem I'm having is that when an object has a property that's an object rather than a simple type, creating a new object inherits the parent's instance of that object, rather than creating a new one. For example:
var aBody = {
arms : 2,
legs : 2
};
var person = {
name : 'Jeff',
body : Object.create(aBody)
};
document.writeln('Person '+person.name+' has '+person.body.arms+' arms and '+person.body.legs+' legs.');
var cat = Object.create(person);
cat.name = 'Bob';
cat.body.arms = 0;
cat.body.legs = 0;
document.writeln('Cat '+cat.name+' has '+cat.body.arms+' arms and '+cat.body.legs+' legs.');
document.writeln('Now person '+person.name+' has '+person.body.arms+' arms and '+person.body.legs+' legs.');
This has output:
Person Jeff has 2 arms and 2 legs.
Cat Bob has 0 arms and 0 legs.
Now person Jeff has 0 arms and 0 legs.
I get the expected behaviour for the simple 'name' property, but not for the 'body'. I think I understand - because JavaScript is copying by reference, no new instance of aBody is spawned. I could manually do this each time I create an object from person
with e.g. cat.body = Object.create(aBody)
but I haven't managed to find a neat way to roll this into the original object definition (here, person
).
I'd really appreciate any guidance you could offer, as I'm trying to learn to write nice, clear, reliable JS code. Is there a clever technique people using the 'purely prototypal' approach have for handling this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
原型对象的全部要点是提供一个地方来容纳类全局属性。因此,您看到的行为实际上是原型继承旨在支持的功能。
如果您不希望实例共享属性,请将属性直接放在实例上。
我会概括 Crock 的函数来检查初始化方法:
不,您可以修改“aBody”:
当您用它创建实例时,它们将拥有自己的“body”属性。
The whole point of a prototype object is to provide a place to house class-global properties. Thus, the behavior your seeing is in fact the feature that prototypal inheritance is intended to support.
If you don't want instances to share properties, put the properties directly on the instances.
I would generalize Crock's function to check for an intialization method:
No you can modify "aBody":
When you create instances with that, they'll have their own "body" property.