Как обрабатывать свойства объекта при использовании подхода чистого прототипирования в JavaScript - PullRequest
0 голосов
/ 07 октября 2011

Я опытный программист, впервые изучающий JavaScript, использующий книгу Дугласа Крокфорда «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 не создается. Я мог бы делать это вручную каждый раз, когда создаю объект из person, например, с помощью cat.body = Object.create(aBody) но мне не удалось найти изящный способ свернуть это в исходное определение объекта (здесь person).

Буду очень признателен за любые рекомендации, которые вы можете предложить, поскольку я пытаюсь научиться писать хороший, понятный и надежный код JS. Есть ли у людей умные методы, использующие «чисто прототипный» подход для решения этой проблемы?

1 Ответ

1 голос
/ 07 октября 2011

Смысл объекта-прототипа состоит в том, чтобы предоставить место для размещения глобальных свойств класса.Таким образом, поведение, которое вы видите, на самом деле является функцией, поддерживаемой наследованием прототипов.

Если вы не хотите, чтобы экземпляры разделяли свойства, поместите свойства непосредственно в экземпляры.

Я бы обобщил функцию Крока, чтобы проверить метод инициализации:

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".

...