Объекты в 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} ---> nullconsole.log(o.a); // 1// Есть ли у объекта 'o' собственное свойство 'a'? // Да, и его значение равно 1console.log(o.b); // 2// Есть ли у объекта 'o' собственное свойство 'b'? // Да, и его значение равно 2.// У прототипа o.[[Prototype]] также есть свойство 'b', // но обращения к нему в данном случае не происходит. // Это и называется "property shadowing" (затенение свойства)console.log(o.c); // 4// Есть ли у объекта 'o' собственное свойство 'с'? // Нет, тогда поищем его в прототипе.// Есть ли у объекта o.[[Prototype]] собственное свойство 'с'? // Да, оно равно 4console.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указывает на наследующий объект (на наследника), а не на прототип, в котором данная функция является собственным свойством.
var o = { a:2,m:function(){returnthis.a +1; }};console.log(o.m()); // 3// в этом случае при вызове 'o.m' this указывает на 'o'var p =Object.create(o);// 'p' - наследник 'o'p.a =12; // создаст собственное свойство 'a' объекта 'p'console.log(p.m()); // 13// при вызове 'p.m' this указывает на 'p'.// т.е. когда 'p' наследует функцию 'm' объекта 'o', // this.a означает 'p.a', собственное свойство 'a' объекта 'p'