0

我是一位经验丰富的程序员,第一次学习 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.

我得到了简单的“名称”属性的预期行为,但没有得到“正文”的预期行为。我想我明白了——因为 JavaScript 是通过引用复制的,所以没有产生新的 aBody 实例。每次person使用 eg创建对象时,我都可以手动执行此操作,cat.body = Object.create(aBody)但我还没有找到一种巧妙的方法将其滚动到原始对象定义中(此处为person)。

我非常感谢您提供的任何指导,因为我正在努力学习编写漂亮、清晰、可靠的 JS 代码。使用“纯原型”方法的人是否有一种巧妙的技术来处理这个问题?

4

1 回答 1

1

原型对象的全部意义在于提供一个存放类全局属性的地方。因此,您看到的行为实际上是原型继承旨在支持的特性。

如果您不希望实例共享属性,请将属性直接放在实例上。

我会概括 Crock 的函数来检查初始化方法:

if (typeof Object.create !== 'function') {
    Object.create = function(o) {
        var F = function () {};
        F.prototype = o;
        var obj = new F();
        if (o.init && typeof o.init === 'function')
          o.init.call(obj);
        return obj;
    };
}

不,您可以修改“aBody”:

var aBody = {
  init: function() {
    this.body = { arms: 2, legs: 2 };
  }
};

当您使用它创建实例时,它们将拥有自己的“body”属性。

于 2011-10-07T13:13:38.410 回答