Skip to content

In JavaScript Class, super cannot access attributes, but can modify attributes?

The super attribute cannot be accessed, but can be modified?

What does super stand for? Some people say it is prototype? I know that the function of Class is in the prototype of the object, but why can super.name ='Lucy'; modify the properties of the object instance?

class a {
  name = 'jack';
  speak() {
    console.log(this.name);
  }
}

class b extends a {
  count() {
    super.name = 'Lucy';
    console.log(super.name) // undefined
    super.speak();
  }
}

new b().count(); // Lucy

Answer

Assigning to super.prop is useful when prop is defined on the parent’s prototype, not when it is defined as an instance property, as is the case with name in your code. Realise that the assignment name = 'jack' happens on the instance that is created by new b, not on some other object.

So when you do super.name = 'Lucy', you are doing nothing else than this.name = 'Lucy'. This change is not visible when you consult super.name after that assignment, because that will scan the parent’s prototype chain, not the instance object. And there is no name defined anywhere on that prototype chain…

The difference between how super.name acts when used for lookup and for assignment is specific: for (non-setter) assignment, it is no different than assigning on this, while for lookup (including setter lookup), it skips this and starts the lookup in the parent’s prototype chain.

The power of the super.prop syntax only reveals itself when you have to deal with methods that have been created on the prototype.

To demonstrate this, let’s define name as a getter/setter function on the prototype:

class A {
  _name = 'jack';
  speak() {
    console.log(this.name);
  }
  get name() {
      return this._name;
  }
  set name(name) {
      return this._name = name + " (A)";
  }
}

class B extends A {
  count() {
    super.name = 'Lucy'; // This will not call the setter of B.prototype, but of A.prototype
    super.speak();
  }
  get name() {
      return this._name;
  }
  set name(name) {
      return this._name + " (B)";
  }
}

new B().count(); // Lucy (A)

Note that here super.name is first identified to be a function in the upper prototype chain, and thus the assignment becomes a function call. If it would have been a property-modifying assignment, it would have happened on this.

See for an elaborate analysis of the specification in this respect in this answer to “ES6 inheritance: uses super to access the properties of the parent class”