alexeykuzmin.com

About simple things

Терминология JavaScript: два прототипа

Перевод статьи Dr. Axel Rauschmayer‘а “JavaScript terminology: the two prototypes”.

К сожалению, в JavaScript’е термин “прототип” (“prototype”) имеет несколько значений.

Прототип 1: связь между объектами

Во-первых, существуют прототипы объектов.
Согласно спецификации ECMAScript, некоторые свойства объектов являются внутренними. Внутренние свойства напрямую недоступны из JavaScript’а, их имена пишутся в двойных квадратных скобках. Одно их таких свойств, [[Prototype]], используется для реализации прототипного наследования. Каждый объект содержит в [[Prototype]] ссылку на свой прототип и т.о. наследует все его свойства. В ECMAScript 5 стало возможно получить ссылку на прототип объекта с помощью функции Object.getPrototypeOf():

1
2
Object.getPrototypeOf({}) === Object.prototype
// true

И возможно создать новый объект, явно указав его прототип, с помощью функции Object.create():

1
2
3
4
var proto = { foo: 123 };
var obj = Object.create(proto);
obj.foo
// 123

Подробнее про обе эти функции можно почитать по ссылке [1]. В ECMAScript 6 можно будет получить ссылку на прототип объекта, используя специальное свойство __proto__ [2].

Прототип 2: свойство конструктора

Во-вторых, каждый конструктор имеет свойство prototype.
Это свойство содержит ссылку на объект, который будет прототипом всех объектов, которые будут созданы с помощью этого конструктора.

1
2
3
4
function Foo() {}
var f = new Foo();
Object.getPrototypeOf(f) === Foo.prototype
// true

Разрешаем конфликт именований

Обычно из контекста понятно, какой из прототипов имеется ввиду. Если всё-таки возникает неопределённость, то под “prototype” приходится понимать прототип объекта, потому что именно в этом смысле этот термин используется в стандартной библиотеке в названии функции getPrototypeOf. Получается, нужно искать другое название для объекта, на который ссылается свойство prototype конструкторов. Можно было бы использовать термин “прототип конструктора” (“constructor prototype”), но это не избавит нас от неоднозначности, потому что у конструкторов тоже есть свой прототип:

1
2
3
function Foo() {}
Object.getPrototypeOf(Foo) === Function.prototype
// true

В итоге, наилучшим вариантом выглядит “прототип экземпляра” (“instance prototype”).

Ссылки

[1] JavaScript inheritance by example
[2] JavaScript: __proto__

Comments