Как работает цепочка вызовов прототипов?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Цепочка прототипов (Prototype Chain) в JavaScript
Цепочка прототипов — это механизм, благодаря которому объекты в JavaScript наследуют свойства и методы друг от друга. Это основа прототипного наследования и ключевая концепция для понимания работы языка.
Что такое прототип?
Прототип — это обычный объект, который служит источником свойств для других объектов. Каждый объект в JavaScript имеет внутреннее скрытое свойство [[Prototype]], которое ссылается на свой прототип.
const parent = { greet: () => 'Привет!' };
const child = Object.create(parent);
console.log(child.greet()); // 'Привет!'
console.log(Object.getPrototypeOf(child) === parent); // true
Как работает поиск свойств?
Когда вы обращаетесь к свойству или методу объекта, JavaScript выполняет поиск в следующем порядке:
- Проверяет свойства самого объекта — собственные свойства
- Если не найдено, ищет в прототипе объекта (
[[Prototype]]) - Затем ищет в прототипе прототипа (и так далее)
- Дошёл до null — свойство не найдено, возвращается undefined
const animal = { sound: 'Некий звук' };
const dog = Object.create(animal);
dog.breed = 'Овчарка';
console.log(dog.breed); // 'Овчарка' — из самого dog
console.log(dog.sound); // 'Некий звук' — из прототипа animal
console.log(dog.name); // undefined — нигде не найдено
Цепочка прототипов
Прототипы могут иметь свои прототипы, образуя цепочку:
const A = { methodA: () => 'A' };
const B = Object.create(A);
B.methodB = () => 'B';
const C = Object.create(B);
C.methodC = () => 'C';
console.log(C.methodA()); // 'A' — найдено в прототипе A
console.log(C.methodB()); // 'B' — найдено в прототипе B
console.log(C.methodC()); // 'C' — в самом C
Цепочка прототипов с конструкторами
При использовании функций-конструкторов цепочка работает через свойство prototype:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return this.name + ' издаёт звук';
};
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
// Устанавливаем цепочку наследования
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
return this.name + ' лает';
};
const myDog = new Dog('Шарик', 'Овчарка');
console.log(myDog.speak()); // 'Шарик издаёт звук'
console.log(myDog.bark()); // 'Шарик лает'
Класс синтаксис (ES6+)
Синтаксис классов упрощает работу с цепочками прототипов:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return this.name + ' издаёт звук';
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
return this.name + ' лает';
}
}
const dog = new Dog('Шарик', 'Овчарка');
console.log(dog.speak()); // 'Шарик издаёт звук'
console.log(dog.bark()); // 'Шарик лает'
Проверка цепочки прототипов
// Проверка наличия свойства в цепочке
console.log('speak' in dog); // true
// Проверка собственного свойства
console.log(dog.hasOwnProperty('name')); // true
console.log(dog.hasOwnProperty('speak')); // false
// Получение прототипа
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
// instanceof
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
Производительность
Чем длиннее цепочка прототипов, тем медленнее поиск свойств. Это важно учитывать при оптимизации.
Ключевые моменты
- Каждый объект имеет [[Prototype]] — ссылку на свой прототип
- Поиск идёт вверх по цепочке — от объекта к прототипам
- null в конце цепочки — Object.prototype.[[Prototype]] === null
- Собственные свойства имеют приоритет над свойствами из прототипа
- Изменение прототипа влияет на все объекты в цепочке
Понимание цепочки прототипов критично для эффективного использования JavaScript и работы с наследованием.