# Sequence of super()?

**URL:** <https://es.discourse.group/t/sequence-of-super/1139>\
**Category:** I have questions\
**Created:** [December 27, 2021, 4:36pm UTC](https://es.discourse.group/t/sequence-of-super/1139 "2021-12-27T16:36:01Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![simonkcleung](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/simonkcleung/32/785_2.png) [@simonkcleung](https://es.discourse.group/u/simonkcleung)\
**Post date:** [December 27, 2021, 4:36pm UTC](https://es.discourse.group/t/sequence-of-super/1139/1 "2021-12-27T16:36:01Z")

</div>

```javascript
class A{
	name = "class A ";
	constructor(){
		this.name = this.name + "A!";
	}
}

console.log((new A()).name);

```

Show **class A A!**  
fine. It sets the name, then call the constructor(). But

```javascript
class A{
   name = "class A ";
   constructor(){
   	this.name = this.name + "A!";
   }
}

class B extends A{
   name = "class B ";
   constructor(){
   	super();
   	this.name = this.name + "B!";
   }
}

console.log((new B()).name);

```

It shows **class B B!**....why? and I expect **class B A!B!**  
Seems super() is hoisted at the beginning of class B, right?

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [December 27, 2021, 6:05pm UTC](https://es.discourse.group/t/sequence-of-super/1139/2 "2021-12-27T18:05:31Z")

</div>

Class fields are all installed as the last step of (or "right after") the super call. This means that `[this.name](http://this.name)` is overwritten with "class B " as soon as the super call is finished.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [December 27, 2021, 8:54pm UTC](https://es.discourse.group/t/sequence-of-super/1139/3 "2021-12-27T20:54:14Z")

</div>

Adding more logs reveals the order:

```javascript
class A {
	name = (console.log("A:1 - init name in A"), "class A ");
	constructor(){
        console.log("A:2 - construct A");
		this.name = this.name + "A!";
	}
}

class B extends A{
   name = (console.log("B:2 - init name in B"), "class B ");
   constructor(){
    console.log("B:1 - construct B");
    try {
      this;
    } catch (e) {
      console.error(e);
    }
    super();
    console.log("B:3 - post super()");
   	this.name = this.name + "B!";
   }
}

```

Gives:

```javascript
new B();

> [Log] B:1 - construct B
> [Error] ReferenceError: 'super()' must be called before accessing |this| or returning non-object.
> [Log] A:1 - init name in A
> [Log] A:2 - construct A
> [Log] B:2 - init name in B
> [Log] B:3 - post super()
```

---

<div class="post-metadata">

**Author:** ![ke67](https://avatars.discourse-cdn.com/v4/letter/k/5f9b8f/32.png) [@ke67](https://es.discourse.group/u/ke67)\
**Post date:** [December 27, 2021, 10:32pm UTC](https://es.discourse.group/t/sequence-of-super/1139/4 "2021-12-27T22:32:32Z")

</div>

Hmmm unrelated but isnt Class A in OP missing a super call? 🤔 Thought you couldn't access `this` without it. Or is it implicit because super in class B is called?

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [December 27, 2021, 11:04pm UTC](https://es.discourse.group/t/sequence-of-super/1139/5 "2021-12-27T23:04:10Z")

</div>

No, base classes don't need (and can't have) `super()`.

---

<div class="post-metadata">

**Author:** ![simonkcleung](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/simonkcleung/32/785_2.png) [@simonkcleung](https://es.discourse.group/u/simonkcleung)\
**Post date:** [December 28, 2021, 3:57pm UTC](https://es.discourse.group/t/sequence-of-super/1139/6 "2021-12-28T15:57:05Z")

</div>

```javascript
var i = 1;
class A{
	name = console.log("Step " + i++ + ": set fields of A");
	constructor(){
		console.log("Step " + i++ + ": run A.constructor()");
	}
}

class B extends A{
	name = console.log("Step " + i++ + ": set fields of B");
	constructor(){
		console.log("Step " + i++ + ": run statements before super() at B.constructor");
		super();
		console.log("Step " + i++ + ": run statements after super() at B.constructor");
	}
}

new B();

```

result:

```javascript
Step 1: run statements before super() at B.constructor
Step 2: set fields of A
Step 3: run A.constructor()
Step 4: set fields of B
Step 5: run statements after super() at B.constructor

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [December 28, 2021, 8:15pm UTC](https://es.discourse.group/t/sequence-of-super/1139/7 "2021-12-28T20:15:12Z")

</div>

May I ask why it behaves this way? I would have expected the same behavior that the O.P. expected, do we know the reasons behind these design choices?

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [December 28, 2021, 8:41pm UTC](https://es.discourse.group/t/sequence-of-super/1139/8 "2021-12-28T20:41:09Z")

</div>

I can't understand that expectation. The design choice here was whether to use [[Define]] or [[Set]], but in either case here, `name = 'Class B ';` would have been the same as `[this.name](http://this.name) = 'Class B';` in the constructor, right after `super()`.

Can you help me understand why you'd expect the public field to do something different?

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [December 28, 2021, 11:18pm UTC](https://es.discourse.group/t/sequence-of-super/1139/9 "2021-12-28T23:18:58Z")

</div>

I guess the natural expectation I would intuitively have is that these class fields execute before any of the constructors run in the prototype chain, so that the fields are fully initialized before any constructor logic begins to execute. But, I guess what I'm describing is probably not possible to do, or easy to implement in JavaScript due to how it's built on this dynamic, prototypal model. I just don't find this current behavior very intuitive (but it might have been the only realistic option) - adding a `super()` call to a constructor is, without warning, causing these class field initializations to be delayed until after the `super()` call happens, instead of before.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [December 29, 2021, 12:09am UTC](https://es.discourse.group/t/sequence-of-super/1139/10 "2021-12-29T00:09:42Z")

</div>

> [@theScottyJam](#):
>
> class fields execute before any of the constructors run in the prototype chain

Class fields are basically syntactic sugar over initialising properties in the constructor. They don't get any special treatment by `new` (i.e. _[[construct]]_).

> [@theScottyJam](#):
>
> Adding a `super()` call to a constructor is, without warning, causing these class field initializations to be delayed until after the `super()` call happens, instead of before.

It's not like you can just "add" that to any constructor. You _have_ to add it when your class `extends` another class, and you must not add it if it doesn't.  
It's just like the rule that you cannot use `this` before the `super()` call.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [December 29, 2021, 1:41am UTC](https://es.discourse.group/t/sequence-of-super/1139/11 "2021-12-29T01:41:49Z")

</div>

> [@bergus](#):
>
> It's just like the rule that you cannot use `this` before the `super()` call.

Yeah, that's also an unintuitive rule for me. I've known it's existed, but have never put much thought into it, as I've just assumed that it's also done due to limitations in how inheritance is built on top of the dynamic prototypal model. I guess it wouldn't be possible to initialize the fields before any constructor runs if the "this" object hasn't even been created yet. And, since a constructor can return any object as the new instance when you "new" it (it doesn't have to return the "this" value), it makes sense that a "this" object can not exist until super() is called, so it seems the way it's currently implemented would be the only valid way to do so within the JavaScript language.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [December 29, 2021, 5:43am UTC](https://es.discourse.group/t/sequence-of-super/1139/12 "2021-12-29T05:43:09Z")

</div>

> [@theScottyJam](#):
>
> Yeah, that's also an unintuitive rule for me.

If helpful, the way I view this is that the classes are effectively constructed in reverse. So `new B` constructs A and then B makes its changes.  
All the subclasses can really do first is decide what arguments to pass down the constructor chain.

So from A’s perspective the only difference when it is constructed directly vs as a subclass is the prototype of `this`. Nothing else about `this` will be any different, this potentially makes classes easier to reason about.
