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

Зачем нужно ключевое слово super?

2.2 Middle🔥 201 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Зачем нужно ключевое слово super

super — это ключевое слово, которое используется в классах для обращения к методам и конструктору родительского класса (класса-родителя). Это критически важно для работы с наследованием и переопределением методов в объектно-ориентированном программировании на JavaScript.

Основная задача super

Когда класс-потомок переопределяет метод или конструктор из класса-родителя, super позволяет:

  1. Вызвать конструктор родителя
  2. Обратиться к методам родителя
  3. Гарантировать, что инициализация прошла корректно

1. super() в конструкторе

Правило: если дочерний класс имеет конструктор, он ОБЯЗАН вызвать super() перед использованием this.

class Animal {
  constructor(name) {
    this.name = name;
    console.log(`Животное: ${name}`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    // ОБЯЗАТЕЛЬНО вызываем super() первым
    super(name); // Вызываем конструктор родителя
    
    this.breed = breed;
    console.log(`Собака: ${breed}`);
  }
}

const dog = new Dog('Рекс', 'Овчарка');
// Вывод:
// Животное: Рекс
// Собака: Овчарка

Что произойдет, если забыть super():

class Dog extends Animal {
  constructor(name, breed) {
    // this.breed = breed; // ReferenceError: Must call super() first!
    super(name);
    this.breed = breed;
  }
}

2. super.method() для вызова методов родителя

Отпределение переопределённого метода через вызов родительского:

class Vehicle {
  start() {
    console.log('Двигатель запущен');
  }

  drive() {
    this.start();
    console.log('Едем');
  }
}

class Car extends Vehicle {
  drive() {
    // Вызываем метод родителя, потом добавляем свою логику
    super.drive(); // Вызовет Vehicle.drive()
    console.log('Едем на автомобиле');
  }
}

const car = new Car();
car.drive();
// Вывод:
// Двигатель запущен
// Едем
// Едем на автомобиле

3. Практический пример: переопределение методов

class Component {
  constructor(props) {
    this.props = props;
  }

  render() {
    return '<div>Base Component</div>';
  }

  onMount() {
    console.log('Component mounted');
  }
}

class Button extends Component {
  constructor(props) {
    super(props);
    this.state = { clicked: false };
  }

  render() {
    // Переопределяем метод, добавляя свою логику
    const baseHTML = super.render();
    return baseHTML.replace('Component', 'Button');
  }

  onClick() {
    this.state.clicked = true;
    console.log('Button clicked');
  }

  onMount() {
    // Вызываем родительский метод, потом добавляем свой код
    super.onMount();
    console.log('Button mounted');
  }
}

const button = new Button({ label: 'Click me' });
button.onMount();
button.onClick();
// Вывод:
// Component mounted
// Button mounted
// Button clicked

4. super с геттерами и сеттерами

class Person {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    this._name = value;
  }
}

class Student extends Person {
  constructor(name, grade) {
    super(name);
    this.grade = grade;
  }

  get name() {
    // Используем геттер родителя
    return `Student: ${super.name}`;
  }

  set name(value) {
    // Используем сеттер родителя
    super.name = value.toUpperCase();
  }
}

const student = new Student('john', 5);
console.log(student.name); // Student: JOHN

5. Множественные уровни наследования

class Animal {
  sound() {
    return 'Издает звук';
  }
}

class Dog extends Animal {
  sound() {
    return super.sound() + ': гав';
  }
}

class GermanShepherd extends Dog {
  sound() {
    return super.sound() + ' громко';
  }
}

const dog = new GermanShepherd();
console.log(dog.sound());
// Вывод: Издает звук: гав громко

Когда super НЕ нужен

// Не переопределяем метод — super не нужен
class Dog extends Animal {
  bark() {
    console.log('Гав!');
  }
}

// Или если не используем родительский метод
class Cat extends Animal {
  meow() {
    return 'Мяу';
  }
}

Важные особенности super

  1. Контекст this — super использует контекст текущего объекта, а не родителя:

    class Parent {
      getName() {
        return 'Parent';
      }
    }
    
    class Child extends Parent {
      getName() {
        console.log(this.constructor.name); // Child
        return super.getName(); // Parent
      }
    }
    
  2. Статические методы — super работает и со статическими методами:

    class Animal {
      static info() {
        return 'Animal class';
      }
    }
    
    class Dog extends Animal {
      static info() {
        return super.info() + ' -> Dog class';
      }
    }
    
    console.log(Dog.info()); // Animal class -> Dog class
    
  3. Обязательность super() — если есть конструктор у дочернего класса, super() вызов обязателен:

    class Parent {}
    class Child extends Parent {
      // Конструктор есть? super() обязателен
      constructor() {
        super(); // Ошибка без этого
      }
    }
    

super в React

Примечание: с переходом на функциональные компоненты и хуки, super стал менее актуален:

// Старый подход с классами
class Button extends React.Component {
  componentDidMount() {
    // Нет super здесь, потому что React.Component это родитель
    console.log('mounted');
  }
}

// Современный подход с хуками
function Button() {
  useEffect(() => {
    console.log('mounted');
  }, []);
}

Резюме

super нужен для:

  • Вызова конструктора родительского класса (обязательно)
  • Обращения к методам родителя при их переопределении
  • Расширения функционала родительского метода, а не полной замены
  • Сохранения инкапсуляции и логики родительского класса

Практическое правило:

  • Если класс наследует другой класс И имеет конструктор -> ОБЯЗАТЕЛЬНО super()
  • Если переопределяешь метод родителя и хочешь использовать его логику -> super.method()
  • Без наследования super не нужен
Зачем нужно ключевое слово super? | PrepBro