На самом деле в JavaScript существует два типа прототипа:
- Одна из них - это «скрытая» ссылка, которую имеет каждый объект (давайте используем
[[Prototype]]
для представления этой скрытой ссылки). по умолчанию для литералов объектов их скрытые ссылки указывают на Object.prototype
, для объектов-функций их скрытые ссылки указывают на Function.prototype
, а для массивов - на Array.prototype
. Эти скрытые ссылки на прототип не связаны со свойствами с именем "prototype". Вы не можете изменить эти скрытые ссылки, добавив или изменив o.prototype
.
- Еще один момент заключается в том, что все функциональные объекты автоматически имеют специальное свойство с именем "
prototype
". Это в основном для использования шаблона вызова конструктора.
[[Prototype]]
используется для поиска свойств (как родитель в классической иерархии), когда свойство не может быть найдено в объекте, вместо него ищется его [[Prototype]]
. Один сценарий использования: скажем, вы хотите добавить свойство ко всем объектам, вы можете просто добавить его к Object.prototype
, который будет автоматически применяться ко всем объектам, поскольку все объекты так или иначе имеют Object.prototype
в качестве [[Prototype]]
корня цепи.
Вернемся к свойству функциональных объектов "prototype
". Это полезно только при использовании с оператором new
. Возьмем следующий фрагмент кода в качестве примера:
function F() {} // function declaration
// F now has a property named "prototype"
var f = new F(); // use "new" operator to create a new function object based on F
То, что new F()
делает выше, - это сначала создать новый функциональный объект, установить [[Prototype]]
(скрытая ссылка) этого вновь созданного функционального объекта равным F.prototype
, а затем вернуть новый функциональный объект. Это, вероятно, то, что вы уже поняли, что работает для функциональных объектов.
Помните, что я сказал, что мы не можем изменить объекты [[Prototype]]
? Ну, по крайней мере, не напрямую. Функция Крокфорда Object.create
делает именно это, используя тот факт, что оператор new
может помочь установить для нас [[Prototype]]
. Таким образом, используя Object.create
, вы сознательно указываете, куда должна указывать скрытая ссылка вашего нового объекта. (что-то вроде указания, кто ваш родительский класс)
В вашем примере conf
- это литерал объекта, а conf.prototype
не очень полезен. Вот еще одна версия с использованием классического стиля:
function ConfBase() {}
ConfBase.prototype.d = 16;
var conf = new ConfBase();
conf.a = 2;
conf.b = 4;
document.writeln(conf.a);
document.writeln(conf.b);
document.writeln(conf.d);
По сравнению с ответом @CMS, я предпочитаю использовать Object.create
. Но, по сути, два стиля используют один и тот же базовый механизм, просто Object.create
помогает привести его в порядок.