почему перечисление фактического конструктора класса в javascript важно


Я читал на javascript garden http://bonsaiden.github.com/JavaScript-Garden/ о прототипе в javascript и один из его примеров выглядит так:

function Foo() {
    this.value = 42;
}
Foo.prototype = {
    method: function() {}
};

function Bar() {}

// Set Bar's prototype to a new instance of Foo
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';

// Make sure to list Bar as the actual constructor <-------------------
Bar.prototype.constructor = Bar;

Обратите внимание на строку, которая читает Make sure to list Bar как фактический конструктор. Я действительно теряюсь в том, что это делает/есть. Я попытался создать новые экземпляры Bar() с последней строкой и без нее. Но вызов " value "или" method " в этих экземплярах возвращает те же самые вещи. Поэтому я задаюсь вопросом, зачем это нужно (я предполагаю должно быть одно) указание конструктора?

Спасибо!!!

2 7

2 ответа:

Каждая функция имеет свойство prototype, оно присваивается при создании объекта функции, оно указывает на вновь созданный объект, который наследуется от Object.prototype, и оно имеет свойство constructor, которое просто указывает на саму функцию.

Назначение свойства prototype - дать способ реализации наследования, используя функции конструктора. Когда вы вызываете функцию с оператором new, она создает новый объект, который наследуется от этого конструктора prototype.

Теперь, назначение свойства constructor состоит в том, чтобы иметь возможность ссылаться на конструктор, создавший объект, например:

function Foo () {}
// default value of the property:
Foo.prototype.constructor == Foo; // true

Это свойство наследуется "экземплярами" Foo, поэтому вы можете знать, какой конструктор использовался для создания объекта:

var foo = new Foo();
foo.constructor == Foo;

Если вы назначаете новый объект прототипу функции, эта связь теряется:

function Bar () {}
Bar.prototype = { inherited: 1 };

Bar.prototype.constructor == Bar;    // false
Bar.prototype.constructor == Object; // true

И это влияет также на экземпляры функции:

var bar = new Bar();
bar.constructor == Bar;    // false
bar.constructor == Object; // true

Другой подобный случай, когда у вас есть два или более уровней наследования с помощью конструкторов, наиболее распространенным способом, используемым для обозначения отношения наследования между функциями, является присвоение свойства prototype второго уровня, например:

function Parent() {}

function Child () {}
Child.prototype = new Parent();
В приведенном выше коде есть несколько проблем, во-первых, он выполняет логику родительского конструктора для создания отношения наследования, но это уже другая история, в приведенном выше примере также затрагивается СВОЙСТВО constructor, так как мы полностью заменяем Child.prototype объект:
var child = new Child();
child.constructor == Parent; // true

Если мы заменим значение свойства constructor Child.prototype после его присвоения, оно покажет ожидаемое поведение:

function Child() {}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child = new Child();
child.constructor == Child; // true

Я полагаю, что это связано с созданием экземпляра Bar с новым ключевым словом. Я считаю, что использование нового будет искать бар.прототип.конструктор. Перед этой линией объект, связанный с баром.прототип.contructor имеет тип Foo, поэтому при создании экземпляра без этой строки он будет создавать объект Foo вместо объекта Bar.