Путаница в установке чего-то. Prototype.__ proto__
В коде для модуля Express для Node.js я наткнулся на эту строку, установив наследование для сервера:
Server.prototype.__proto__ = connect.HTTPServer.prototype;
Я не уверен, что это делает - документы MDC (https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited#prototype_and_ proto), похоже, говорят, что я мог просто выполните:
Server.prototype = connect.HTTPServer.prototype;
Действительно, я сделал это испытание:
var parent = function(){}
parent.prototype = {
test: function(){console.log('test')};
}
var child1 = function(){};
child1.prototype = parent.prototype;
var instance1 = new child1();
instance1.test(); // 'test'
var child2 = function(){};
child2.prototype.__proto__ = parent.prototype;
var instance2 = new child2();
instance2.test(); // 'test'
Кажется, что то же самое? Итак, да, мне интересно, какой параметр object.prototype.__ proto для. Спасибо!
Ответы
Ответ 1
Посмотрите на диаграмму на этой странице (mckoss.com), которая показывает отношения prototype
, constructor
, __proto__
для небольшой иерархии, Также код ниже диаграммы достаточно хорошо описывает отношение.
Когда у вас есть функция Base
и задан прототип объекта функции, оператор Derived.prototype = new Base;
автоматически устанавливает __proto__
(фактически внутренний [[prototype]]
) Derived.prototype
в Base.prototype
make Производит сам класс, из которого вы можете создавать объекты. Кажется, это более стандартный способ определения производного класса.
Из того, что я читаю, __proto__
является нестандартным способом доступа к внутреннему [[prototype]]
объекта. Кажется, это хорошо поддерживается, но я не уверен, что ему следует доверять.
В любом случае ваш пример Server.prototype.__proto__ = connect.HTTPServer.prototype;
, похоже, делает вывод наоборот: сначала определите объект, Server
, определив конструктор и прото, а затем вручную подключите внутренний [[prototype]]
к морфию это в класс, полученный из HTTPServer
.
Что касается предложенной вами альтернативы, Server.prototype = connect.HTTPServer.prototype;
: это плохая идея. Здесь вы устанавливаете прототип Server
для того же объекта, что и прототип HTTPServer
. Поэтому любые изменения, внесенные вами в класс Server
, будут непосредственно отражены в HTTPServer
и будут доступны из других производных классов HTTPServer
. Вы можете изобразить хаос, если два класса, полученные из HTTPServer
, попытаются определить один и тот же элемент.
Ответ 2
Нестандартное свойство __proto__
позволяет вам установить прототип существующего объекта.
В вашем примере обе версии достигнут того же эффекта, но есть разница:
Прототип child1
такой же, как прототип parent
, тогда как прототип child2
- пустой объект, и этот прототип пустого объекта совпадает с прототипом parent
.
Конечно, как child2
, а его прототип не имеет метода test
, этот метод будет рассмотрен далее в цепочке прототипов.
Также рассмотрим следующее:
Вы хотите создать только один объект, который должен наследовать от другого объекта. Теперь вы можете написать конструктор, но JavaScript имеет объектную нотацию для создания объектов напрямую и вы хотите использовать его.
Если у вас есть функция-конструктор, то позволить новым объектам наследовать от другого объекта так же легко настроить prototype
функции-конструктора на этот объект.
Очевидно, это не работает для объектных литералов. Но в Firefox вы можете использовать __proto__
для его установки:
var server = {
__proto__: connect.HTTPServer.prototype,
other: properties
};
Поскольку это свойство не является стандартным, его следует избегать.