super
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2016.
Thesuper keyword is used to access properties on an object literal or class's [[Prototype]], or invoke a superclass's constructor.
Thesuper.prop andsuper[expr] expressions are valid in anymethod definition in bothclasses andobject literals. Thesuper(...args) expression is valid in class constructors.
In this article
Try it
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"Syntax
super()super(arg1)super(arg1, arg2)super(arg1, arg2, /* …, */ argN)super.propertyOnParentsuper[expression]Description
Thesuper keyword can be used in two ways: as a "function call" (super(...args)), or as a "property lookup" (super.prop andsuper[expr]).
Note:super is a keyword and these are special syntactic constructs.super is not a variable that points to the prototype object. Attempting to readsuper itself is aSyntaxError.
const child = { myParent() { console.log(super); // SyntaxError: 'super' keyword unexpected here },};In theconstructor body of a derived class (withextends), thesuper keyword may appear as a "function call" (super(...args)), which must be called before thethis keyword is used, and before the constructor returns. It calls the parent class's constructor and binds the parent class's public fields, after which the derived class's constructor can further access and modifythis.
The "property lookup" form can be used to access methods and properties of an object literal's or class's [[Prototype]]. Within a class's body, the reference ofsuper can be either the superclass's constructor itself, or the constructor'sprototype, depending on whether the execution context is instance creation or class initialization. See the Examples section for more details.
Note that the reference ofsuper is determined by the class or object literalsuper was declared in, not the object the method is called on. Therefore, unbinding or re-binding a method doesn't change the reference ofsuper in it (although they do change the reference ofthis). You can seesuper as a variable in the class or object literal scope, which the methods create a closure over. (But also beware that it's not actually a variable, as explained above.)
When setting properties throughsuper, the property is set onthis instead.
Examples
>Using super in classes
This code snippet is taken from theclasses sample (live demo). Heresuper() is called to avoid duplicating the constructor parts' that are common betweenRectangle andSquare.
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-calling static methods
You are also able to call super onstatic methods.
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'Accessing super in class field declaration
super can also be accessed during class field initialization. The reference ofsuper depends on whether the current field is an instance field or a static field.
class Base { static baseStaticField = 90; baseMethod() { return 10; }}class Extended extends Base { extendedField = super.baseMethod(); // 10 static extendedStaticField = super.baseStaticField; // 90}Note that instance fields are set on the instance instead of the constructor'sprototype, so you can't usesuper to access the instance field of a superclass.
class Base { baseField = 10;}class Extended extends Base { extendedField = super.baseField; // undefined}Here,extendedField isundefined instead of 10, becausebaseField is defined as an own property of theBase instance, instead ofBase.prototype.super, in this context, only looks up properties onBase.prototype, because that's the [[Prototype]] ofExtended.prototype.
Deleting super properties will throw an error
You cannot use thedelete operator andsuper.prop orsuper[expr] to delete a parent class' property — it will throw aReferenceError.
class Base { foo() {}}class Derived extends Base { delete() { delete super.foo; // this is bad }}new Derived().delete(); // ReferenceError: invalid delete involving 'super'.Using super.prop in object literals
Super can also be used in theobject initializer notation. In this example, two objects define a method. In the second object,super calls the first object's method. This works with the help ofObject.setPrototypeOf() with which we are able to set the prototype ofobj2 toobj1, so thatsuper is able to findmethod1 onobj1.
const obj1 = { method1() { console.log("method 1"); },};const obj2 = { method2() { super.method1(); },};Object.setPrototypeOf(obj2, obj1);obj2.method2(); // Logs "method 1"Methods that read super.prop do not behave differently when bound to other objects
Accessingsuper.x behaves likeReflect.get(Object.getPrototypeOf(objectLiteral), "x", this), which means the property is always sought on the object literal/class declaration's prototype, and unbinding and re-binding a method won't change the reference ofsuper.
class Base { baseGetX() { return 1; }}class Extended extends Base { getX() { return super.baseGetX(); }}const e = new Extended();console.log(e.getX()); // 1const { getX } = e;console.log(getX()); // 1The same happens in object literals.
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"Only resetting the entire inheritance chain will change the reference ofsuper.
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 inheritanceObject.setPrototypeOf(Extended.prototype, AnotherBase.prototype);console.log(e.getX()); // Logs "2" instead of "1", because the prototype chain has changedconsole.log(Extended.staticGetX()); // Still logs "3", because we haven't modified the static part yet// Reset static inheritanceObject.setPrototypeOf(Extended, AnotherBase);console.log(Extended.staticGetX()); // Now logs "4"Calling methods from super
When callingsuper.prop as a function, thethis value inside theprop function is the currentthis, not the object thatsuper points to. For example, thesuper.getName() call logs"Extended", despite the code looking like it's equivalent toBase.getName().
class Base { static getName() { console.log(this.name); }}class Extended extends Base { static getName() { super.getName(); }}Extended.getName(); // Logs "Extended"This is especially important when interacting withstatic private elements.
Setting super.prop sets the property on this instead
Setting properties ofsuper, such assuper.x = 1, behaves likeReflect.set(Object.getPrototypeOf(objectLiteral), "x", 1, this). This is one of the cases where understandingsuper as simply "reference of the prototype object" falls short, because it actually sets the property onthis instead.
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")); // truesuper.x = 1 will look for the property descriptor ofx onA.prototype (and invoke the setters defined there), but thethis value will be set tothis, which isb in this context. You can readReflect.set for more details on the case whentarget andreceiver differ.
This means that while methods thatgetsuper.prop are usually not susceptible to changes in thethis context, those thatsetsuper.prop are.
/* Reusing same declarations as above */const b2 = new B();b2.setX.call(null); // TypeError: Cannot assign to read only property 'x' of object 'null'However,super.x = 1 still consults the property descriptor of the prototype object, which means you cannot rewrite non-writable properties, and setters will be invoked.
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-onlyconsole.log(y.prop); // 1Specifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-super-keyword> |