Basics

Наследование свойств

Объекты в JavaScript — динамические "контейнеры", наполненные свойствами (называемыми собственными свойствами). Каждый объект содержит ссылку на свой объект-прототип. При попытке получить доступ к какому-либо свойству объекта, свойство вначале выискивается в самом объекте, затем — в прототипе объекта, после чего — в прототипе прототипа, и так далее. Поиск ведется до тех пор, пока не найдено свойство с совпадающим именем или не достигнут конец цепочки прототипов.

// В этом примере someObject.[[Prototype]] означает прототип someObject. 
// Это упрощённая нотация (описанная в стандарте ECMAScript). 
// Она не может быть использована в реальных скриптах.

// Допустим, у нас есть объект 'o' с собственными свойствами a и b
// {a:1, b:2} 

// o.[[Prototype]] имеет свойства b и с
// {b:3, c:4}

// Далее, o.[[Prototype]].[[Prototype]] является null
// null - это окончание в цепочке прототипов 
// по определению, null не имеет свойства [[Prototype]]

// В итоге полная цепочка прототипов выглядит так:
// {a:1, b:2} ---> {b:3, c:4} ---> null

console.log(o.a); // 1
// Есть ли у объекта 'o' собственное свойство 'a'? 
// Да, и его значение равно 1

console.log(o.b); // 2
// Есть ли у объекта 'o' собственное свойство 'b'? 
// Да, и его значение равно 2.
// У прототипа o.[[Prototype]] также есть свойство 'b', 
// но обращения к нему в данном случае не происходит. 
// Это и называется "property shadowing" (затенение свойства)

console.log(o.c); // 4
// Есть ли у объекта 'o' собственное свойство 'с'? 
// Нет, тогда поищем его в прототипе.
// Есть ли у объекта o.[[Prototype]] собственное свойство 'с'? 
// Да, оно равно 4

console.log(o.d); // undefined
// Есть ли у объекта 'o' собственное свойство 'd'? 
// Нет, тогда поищем его в прототипе.
// Есть ли у объекта o.[[Prototype]] собственное свойство 'd'? 
// Нет, продолжаем поиск по цепочке прототипов.
// o.[[Prototype]].[[Prototype]] равно null, прекращаем поиск, 
// свойство не найдено, возвращаем undefined

При добавлении к объекту нового свойства, создаётся новое собственное свойство (own property). Единственным исключением из этого правила являются наследуемые свойства, имеющие getter или setter.

Наследование "методов"

JavaScript не имеет "методов" в смысле, принятом в классической модели ООП. В JavaScript любая функция может быть добавлена к объекту в виде его свойства. Унаследованная функция ведёт себя точно так же, как любое другое свойство объекта, в том числе и в плане "затенения свойств" (property shadowing), как показано в примере выше (в данном конкретном случае это форма переопределения метода - method overriding).

В области видимости унаследованной функции ссылкаthisуказывает на наследующий объект (на наследника), а не на прототип, в котором данная функция является собственным свойством.

Last updated