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

Что наследуется?

1.8 Middle🔥 111 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Наследование в JavaScript: что и как передаётся

В JavaScript под "наследованием" обычно понимают механизм прототипного наследования, который существенно отличается от классического наследования в языках вроде Java или C++. Однако, если говорить о наследовании в контексте ES6 классов (которые являются "синтаксическим сахаром" над прототипами), можно выделить следующие аспекты.

Что наследуется при использовании ES6 классов

class Animal {
  constructor(name) {
    this.name = name;
    this.type = 'животное';
  }
  
  speak() {
    return `${this.name} издает звук`;
  }
  
  static isAnimal(obj) {
    return obj instanceof Animal;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
  
  speak() {
    return `${this.name} гавкает`;
  }
}

1. Экземплярные методы и свойства

  • Методы, объявленные в теле родительского класса (например, speak()), наследуются экземплярами дочернего класса через цепочку прототипов.
  • Важно: конструктор (constructor) не наследуется автоматически - его нужно явно вызывать через super().
const myDog = new Dog('Бобик', 'овчарка');
console.log(myDog.speak()); // "Бобик гавкает" 
// Хотя speak переопределён, доступ к родительской версии возможен через super.speak()

2. Свойства экземпляра, инициализированные в конструкторе

  • Свойства, присвоенные через this.property = value в конструкторе родителя, наследуются при условии вызова super().
console.log(myDog.name); // "Бобик" - унаследовано от Animal
console.log(myDog.type); // "животное" - унаследовано от Animal
console.log(myDog.breed); // "овчарка" - собственное свойство Dog

3. Статические методы и свойства

  • Статические методы (через ключевое слово static) также наследуются:
console.log(Dog.isAnimal(myDog)); // true - статический метод унаследован

4. Геттеры и сеттеры

  • Accessors (get/set) наследуются аналогично обычным методам:
class Animal {
  get description() {
    return `Это ${this.name}, тип: ${this.type}`;
  }
}

console.log(myDog.description); // Унаследованный геттер работает

Что НЕ наследуется "напрямую"

1. Приватные поля (ES2022+)

  • Поля, объявленные с #, не наследуются:
class Animal {
  #secret = 'секрет животного';
  
  getSecret() {
    return this.#secret;
  }
}

class Dog extends Animal {}

const dog = new Dog();
// console.log(dog.#secret); // SyntaxError
console.log(dog.getSecret()); // "секрет животного" - доступ через публичный метод

2. Свойства в конструкторе без super()

  • Если в дочернем классе не вызвать super(), свойства родителя не будут инициализированы:
class BadDog extends Animal {
  constructor(name) {
    // Отсутствует super(name) - будет ошибка
    this.breed = 'дворняга';
  }
}
// new BadDog() // ReferenceError: Must call super constructor...

3. Свойства, добавленные вручную после определения класса

  • Свойства, добавленные в прототип родителя после наследования, всё равно доступны благодаря динамической природе цепочки прототипов:
Animal.prototype.newMethod = function() { return 'новый метод'; };
console.log(myDog.newMethod()); // "новый метод" - доступен!

Прототипная модель под капотом

На самом деле, ES6 классы - это синтаксический сахар над прототипами:

// То, что происходит на самом деле
function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  return `${this.name} издает звук`;
};

function Dog(name, breed) {
  Animal.call(this, name); // Аналог super()
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype); // Установка прототипной цепочки
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function() {
  return `${this.name} гавкает`;
};

Ключевые особенности наследования в JavaScript

  • Цепочка прототипов: При обращении к свойству объекта JavaScript сначала ищет его в самом объекте, затем в его прототипе, затем в прототипе прототипа и так далее.
  • Динамическое наследование: Можно менять прототипы "на лету", что влияет на все экземпляры.
  • Единое наследование: JavaScript поддерживает только одиночное наследование (один родитель).
  • Mixins и композиция: Для множественного "наследования" часто используют миксины или композицию.

Практические рекомендации

  1. Всегда вызывайте super() в конструкторе дочернего класса до использования this
  2. Для переопределения методов используйте ту же сигнатуру и вызывайте super.method() при необходимости
  3. Предпочитайте композицию наследованию в сложных иерархиях
  4. Помните о instanceof и isPrototypeOf() для проверки цепочки наследования

Наследование в JavaScript - мощный, но требующий понимания механизм. Глубокое понимание прототипной модели позволяет писать более эффективный и гибкий код, правильно выбирая между наследованием, композицией и другими паттернами проектирования.

Что наследуется? | PrepBro