Prototype Chain
В одной фразе: прототипная цепочка — механизм делегирования свойств в JS: при обращении к свойству движок ищет его на объекте, затем поднимается по [[Prototype]] до Object.prototype, где цепочка заканчивается null. На собесе важно разграничить proto, .prototype и Object.getPrototypeOf().
[instance]─[[P]]─>[Foo.prototype]─[[P]]─>[Object.prototype]─[[P]]─>null .x=1 .greet() .toString() .constructor=Foo .hasOwnProperty()
function Foo(x) { this.x = x; }Foo.prototype.greet = function () { return `x=${this.x}`; };
const obj = new Foo(1);
// Поиск свойства: own → Foo.prototype → Object.prototypeobj.x; // 1 — own propertyobj.greet(); // 'x=1' — из Foo.prototype (делегирование)obj.toString(); // '[object Object]' — из Object.prototype
obj.hasOwnProperty('x'); // trueobj.hasOwnProperty('greet'); // false — greet на prototype, не на obj// Object.create: задать [[Prototype]] явноconst animal = { breathe() { return `${this.name} breathes`; }};const dog = Object.create(animal);dog.name = 'Rex';dog.breathe(); // 'Rex breathes' — делегирует к animal
// Object.create(null): объект без цепочки — чистый словарьconst dict = Object.create(null);dict.key = 'value';dict.toString; // undefined — нет Object.prototype в цепочке// Безопасен для хранения произвольных ключей (нет коллизий с toString и др.)// Разбираем три "прото":function Bar() {}const b = new Bar();
// 1. Bar.prototype — объект где хранятся методы для экземпляров// 2. Object.getPrototypeOf(b) — [[Prototype]] экземпляра b// 3. b.__proto__ — устаревший геттер (не использовать в продакшене)
Bar.prototype === Object.getPrototypeOf(b); // trueb instanceof Bar; // true (ищет Bar.prototype в цепочке [[Prototype]] b)b instanceof Object; // true (Object.prototype тоже в цепочке)Итог: Prototype chain — живые ссылки: добавление метода в Foo.prototype после создания экземпляров сразу видно всем экземплярам.