← Назад к вопросам

Как работает цепочка вызовов прототипов?

2.0 Middle🔥 181 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Цепочка прототипов (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 выполняет поиск в следующем порядке:

  1. Проверяет свойства самого объекта — собственные свойства
  2. Если не найдено, ищет в прототипе объекта ([[Prototype]])
  3. Затем ищет в прототипе прототипа (и так далее)
  4. Дошёл до 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 и работы с наследованием.