Spec-Zone.ru › JavaScript

super

Базовая поддержка Широко доступно

Эта возможность хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с марта 2016 года.

Ключевое слово super используется для доступа к свойствам в [[Prototype]] литерала объекта или класса, либо для вызова конструктора суперкласса.

Выражения super.prop и super[expr] допустимы в любом определении метода как в классах, так и в литералах объектов. Выражение super(...args) допустимо в конструкторах классов.

Попробуйте

class Foo {
  constructor(name) {
    this.name = name;
  }

  getNameSeparator() {
    return "-";
  }
}

class FooBar extends Foo {
  constructor(name, index) {
    super(name);
    this.index = index;
  }

  // Does not get called
  getNameSeparator() {
    return "/";
  }

  getFullName() {
    return this.name + super.getNameSeparator() + this.index;
  }
}

const firstFooBar = new FooBar("foo", 1);

console.log(firstFooBar.name);
// Expected output: "foo"

console.log(firstFooBar.getFullName());
// Expected output: "foo-1"

Синтаксис

super()
super(arg1)
super(arg1, arg2)
super(arg1, arg2, /* …, */ argN)

super.propertyOnParent
super[expression]

Описание

Ключевое слово super может использоваться двумя способами: как "вызов функции" (super(...args)) или как "поиск свойства" (super.prop и super[expr]).

Примечание: super — это ключевое слово, и это специальные синтаксические конструкции. super не является переменной, указывающей на объект-прототип. Попытка прочитать сам super приводит к SyntaxError.

js-nolint example-bad const child = { myParent() { console.log(super); // SyntaxError: 'super' keyword unexpected here }, };

В теле конструктора производного класса (с extends) ключевое слово super может использоваться как "вызов функции" (super(...args)), который должен быть вызван до использования ключевого слова this и до возврата конструктора. Он вызывает конструктор родительского класса и связывает общедоступные поля родительского класса, после чего конструктор производного класса может в дальнейшем получать доступ и изменять this.

Форма "поиска свойства" может использоваться для доступа к методам и свойствам [[Prototype]] литерала объекта или класса. Внутри тела класса ссылка super может быть либо самим конструктором суперкласса, либо prototype конструктора, в зависимости от того, является ли контекст выполнения созданием экземпляра или инициализацией класса. Дополнительные сведения см. в разделе Примеры.

Обратите внимание, что ссылка super определяется классом или литералом объекта, в котором был объявлен super, а не объектом, на котором вызывается метод. Следовательно, отвязка или повторная привязка метода не изменяет ссылку super в нем (хотя они изменяют ссылку this). Вы можете рассматривать super как переменную в области видимости класса или литерала объекта, над которой методы создают замыкание. (Но также помните, что это на самом деле не переменная, как объяснялось выше.)

При установке свойств через super свойство устанавливается вместо этого на this.

Примеры

Использование super в классах

Этот фрагмент кода взят из примера классов (живая демонстрация). Здесь вызывается super(), чтобы избежать дублирования частей конструктора, общих для Rectangle и Square.

class Rectangle {
  constructor(height, width) {
    this.name = "Rectangle";
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log(`Hi, I am a ${this.name}.`);
  }
  get area() {
    return this.height * this.width;
  }
  set area(value) {
    this._area = value;
  }
}

class Square extends Rectangle {
  constructor(length) {
    // Here, it calls the parent class's constructor with lengths
    // provided for the Rectangle's width and height
    super(length, length);

    // Note: In derived classes, super() must be called before you
    // can use 'this'. Moving this to the top causes a ReferenceError.
    this.name = "Square";
  }
}

Вызов статических методов через super

Вы также можете вызывать super для статических методов.

class Rectangle {
  static logNbSides() {
    return "I have 4 sides";
  }
}

class Square extends Rectangle {
  static logDescription() {
    return `${super.logNbSides()} which are all equal`;
  }
}
Square.logDescription(); // 'I have 4 sides which are all equal'

Доступ к super при объявлении полей класса

Доступ к super также можно получить во время инициализации полей класса. Ссылка super зависит от того, является ли текущее поле полем экземпляра или статическим полем.

class Base {
  static baseStaticField = 90;
  baseMethod() {
    return 10;
  }
}

class Extended extends Base {
  extendedField = super.baseMethod(); // 10
  static extendedStaticField = super.baseStaticField; // 90
}

Обратите внимание, что поля экземпляра устанавливаются для экземпляра, а не для prototype конструктора, поэтому вы не можете использовать super для доступа к полю экземпляра суперкласса.

class Base {
  baseField = 10;
}

class Extended extends Base {
  extendedField = super.baseField; // undefined
}

Здесь extendedField является undefined вместо 10, потому что baseField определяется как собственное свойство экземпляра Base, а не Base.prototype. super в этом контексте ищет свойства только на Base.prototype, потому что это [[Prototype]] объекта Extended.prototype.

Удаление свойств super вызовет ошибку

Вы не можете использовать оператор delete и super.prop или super[expr] для удаления свойства родительского класса — это приведет к ReferenceError.

class Base {
  foo() {}
}
class Derived extends Base {
  delete() {
    delete super.foo; // this is bad
  }
}

new Derived().delete(); // ReferenceError: invalid delete involving 'super'.

Использование super.prop в литералах объектов

Super также может использоваться в нотации инициализатора объекта. В этом примере два объекта определяют метод. Во втором объекте super вызывает метод первого объекта. Это работает с помощью Object.setPrototypeOf(), с помощью которого мы можем установить прототип obj2 на obj1, чтобы super мог найти method1 на obj1.

const obj1 = {
  method1() {
    console.log("method 1");
  },
};

const obj2 = {
  method2() {
    super.method1();
  },
};

Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // Logs "method 1"

Методы, читающие super.prop, не ведут себя по-другому при привязке к другим объектам

Доступ к super.x ведет себя как Reflect.get(Object.getPrototypeOf(objectLiteral), "x", this), что означает, что свойство всегда ищется в прототипе объявления литерала объекта/класса, и отвязка или повторная привязка метода не изменят ссылку super.

class Base {
  baseGetX() {
    return 1;
  }
}
class Extended extends Base {
  getX() {
    return super.baseGetX();
  }
}

const e = new Extended();
console.log(e.getX()); // 1
const { getX } = e;
console.log(getX()); // 1

То же самое происходит в литералах объектов.

const parent1 = { prop: 1 };
const parent2 = { prop: 2 };

const child = {
  myParent() {
    console.log(super.prop);
  },
};

Object.setPrototypeOf(child, parent1);
child.myParent(); // Logs "1"

const myParent = child.myParent;
myParent(); // Still logs "1"

const anotherChild = { __proto__: parent2, myParent };
anotherChild.myParent(); // Still logs "1"

Только сброс всей цепочки наследования изменит ссылку super.

class Base {
  baseGetX() {
    return 1;
  }
  static staticBaseGetX() {
    return 3;
  }
}
class AnotherBase {
  baseGetX() {
    return 2;
  }
  static staticBaseGetX() {
    return 4;
  }
}
class Extended extends Base {
  getX() {
    return super.baseGetX();
  }
  static staticGetX() {
    return super.staticBaseGetX();
  }
}

const e = new Extended();
// Reset instance inheritance
Object.setPrototypeOf(Extended.prototype, AnotherBase.prototype);
console.log(e.getX()); // Logs "2" instead of "1", because the prototype chain has changed
console.log(Extended.staticGetX()); // Still logs "3", because we haven't modified the static part yet
// Reset static inheritance
Object.setPrototypeOf(Extended, AnotherBase);
console.log(Extended.staticGetX()); // Now logs "4"

Вызов методов через super

При вызове super.prop как функции, значение this внутри функции prop является текущим this, а не объектом, на который указывает super. Например, вызов super.getName() регистрирует "Extended", хотя код выглядит так, как будто он эквивалентен Base.getName().

class Base {
  static getName() {
    console.log(this.name);
  }
}

class Extended extends Base {
  static getName() {
    super.getName();
  }
}

Extended.getName(); // Logs "Extended"

Это особенно важно при взаимодействии со статическими приватными элементами.

Установка super.prop устанавливает свойство на this вместо этого

Установка свойств super, таких как super.x = 1, ведет себя как Reflect.set(Object.getPrototypeOf(objectLiteral), "x", 1, this). Это один из случаев, когда понимание super как просто "ссылки на объект-прототип" является неполным, потому что на самом деле оно устанавливает свойство на this вместо этого.

class A {}
class B extends A {
  setX() {
    super.x = 1;
  }
}

const b = new B();
b.setX();
console.log(b); // B { x: 1 }
console.log(Object.hasOwn(b, "x")); // true

super.x = 1 будет искать дескриптор свойства x на A.prototype (и вызывать определенные там сеттеры), но значение this будет установлено в this, которое является b в этом контексте. Вы можете прочитать Reflect.set для получения более подробной информации о случае, когда target и receiver различаются.

Это означает, что хотя методы, которые получают super.prop, обычно не подвержены изменениям в контексте this, те, которые устанавливают super.prop, подвержены.

/* Reusing same declarations as above */

const b2 = new B();
b2.setX.call(null); // TypeError: Cannot assign to read only property 'x' of object 'null'

Однако super.x = 1 по-прежнему обращается к дескриптору свойства объекта-прототипа, что означает, что вы не можете перезаписать свойства, которые не могут быть записаны, и будут вызываться сеттеры.

class X {
  constructor() {
    // Create a non-writable property
    Object.defineProperty(this, "prop", {
      configurable: true,
      writable: false,
      value: 1,
    });
  }
}

class Y extends X {
  constructor() {
    super();
  }
  foo() {
    super.prop = 2; // Cannot overwrite the value.
  }
}

const y = new Y();
y.foo(); // TypeError: "prop" is read-only
console.log(y.prop); // 1

Спецификации

Спецификация
Спецификация языка ECMAScript® 2027
# sec-super-keyword

Совместимость с браузерами

Desktop Mobile Server
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
super
42
13
45
29
7
42
45
29
7
4.0
42
7
1.0.0
1.0
6.0.0

См. также

  • Классы

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API