Свойство __proto__

Каждый объект содержит специальное свойство __proto__, которое позволяет получить доступ для чтения (getter) и записи (setter) к прототипу объекта (обозначается в спецификации как [[Prototype]]). С помощью этого свойства мы можем расширить объект за счет наследования свойств другого объекта:

let objA = { a: 10 };
let objB = { b: 55 };
objB.__proto__ = objA;
console.log(objB.a);       // 10
console.log(objB.b);       // 55

В этом примере объект objB наследует свойства объекта objA. С помощью точечной нотации мы можем получить доступ как к собственному свойству b, так и к унаследованному в цепочке прототипов свойству a.

Свойство __proto__ можно также указать внутри фигурных скобок. Давайте создадим объект objC, который наследует все свойства объектов objB и objA:

let objC = {
   b: 22,
   c: 32,
   __proto__: objB
};
console.log(objC.a);       // 10
console.log(objC.b);       // 22, а не 55 !
console.log(objC.c);       // 32

Вначале просматриваются все собственные свойства объекта, если свойство не найдено, то поиск свойства производится в цепочке прототипов. В нашем примере внутри объекта objC мы создали свойство b, которое переопределяет одноименное свойство из объекта objB. Поэтому свойство b будет найдено в текущем объекте и поиск будет прекращен. В итоге мы получим значение 22.

Все объекты по умолчанию наследуют свойства класса Object. Поэтому, создав пустой объект, мы можем получить доступ, например, к методу toString(), определенному в классе Object:

let obj = {};
console.log( obj.toString() ); // [object Object]

Если свойству __proto__ присвоить значение null, то объект не будет наследником класса Object:

let obj = {
   a: 1,
   __proto__: null
};
console.log( obj.a );          // 1
console.log( obj.toString );   // undefined

Создать объект без наследования свойств класса Object позволяет статический метод create(null) из класса Object:

let obj = Object.create(null);
obj.a = 1;
console.log( obj.a );          // 1
console.log( obj.toString );   // undefined

Свойство __proto__ считается устаревшим, хотя и поддерживается Node.js и Web-браузерами. Вместо него лучше использовать статические методы setPrototypeOf() и getPrototypeOf() из класса Object:

<Объект>   = setPrototypeOf(<Объект>, <Прототип>)
<Прототип> = getPrototypeOf(<Объект>)

Пример:

let objA = { a: 10 };
let objB = { b: 55 };
Object.setPrototypeOf(objB, objA);
console.log(objB.a);                        // 10
console.log(objB.b);                        // 55
console.log( Object.getPrototypeOf(objB) ); // { a: 10 }

Пример создания объекта без наследования свойств класса Object:

let obj = Object.setPrototypeOf({}, null);
obj.a = 1;
console.log( obj.a );          // 1
console.log( obj.toString );   // undefined

Метод objA.isPrototypeOf(objB) из класса Object возвращает значение true, если объект objA существует в цепочке прототипов объекта objB:

let objA = { a: 10 };
let objB = { b: 55 };
let objC = {};
Object.setPrototypeOf(objB, objA);
console.log( objA.isPrototypeOf(objB) ); // true
console.log( objA.isPrototypeOf(objC) ); // false
Object.setPrototypeOf(objC, objB);
console.log( objA.isPrototypeOf(objC) ); // true
На заметку

Учебник по Node.js и JavaScript
Учебник по JavaScript (Node.js) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов