# JS Tip of the Day: Constructor Internals

**URL:** <https://forum.kirupa.com/t/js-tip-of-the-day-constructor-internals/643090>\
**Category:** web dev\
**Created:** [May 16, 2020, 2:56pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-constructor-internals/643090 "2020-05-16T14:56:24Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [May 16, 2020, 2:56pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-constructor-internals/643090/1 "2020-05-16T14:56:24Z")

</div>

**Constructor Internals**  
Version: ES2015 (class syntax)  
Level: Intermediate

When using constructors to create custom object instances, there’s a little bit of magic that happens in the background when the constructor is being used. This is the unwritten behavior that makes constructors useful and do what they do. Here we’ll look at what that magic is for both function and class-based constructors.

Function-based constructors are the simplest of the kinds of constructors. They do a little magic, but not as much as their `class` counterparts. When you write a function constructor, you’re mostly only responsible for assigning properties to the instance. The creation of the instance itself and the returning of it from the constructor call is handled automatically for you.

Note: All of the following sample code assumes constructors being called with `new` and denotes internal (or “magic”) behavior with `//~` comments.

```javascript
function User (name) {
    //~ this = Object.create(User.prototype);
    this.name = name;
    //~ return this;
}
//~ User.prototype = { constructor: User };

```

Here you can see when the function is declared, because its a function that can be used as a constructor, a `prototype` property is automatically assigned to it. Then, when called as a constructor, a new instance is created based on that `prototype`, assigned to `this`, and automatically returned after all user code (here, `this.name = name`) has run.

One thing function constructors don’t help with much is when extending other constructors. No additional magic is provided; it’s all manual.

```javascript
function Person () {}
//~ Person.prototype = { constructor: Person };

function User (name) {
    //~ this = Object.create(User.prototype);
    Person.call(this); // manual super()
    this.name = name;
    //~ return this;
}
//~ User.prototype = { constructor: User };

// manual extends
User.prototype = Object.create(Person);
User.prototype.constructor = User;

```

The `class` syntax offers a new way to write constructors in JavaScript. The end result is largely the same - a function you use to create new object instances, but `class` offers features not available in function-based constructors, like the use of `super`.

When it comes to `class` base classes, you have help similar to that found in function-based constructors.

```javascript
class User {
    constructor (name) { // function representing User
        //~ this = Object.create(User.prototype);
        this.name = name;
        //~ return this;
    }
}
//~ User.prototype = { constructor: User };

```

But once you extend another class, you start to see all the benefits that were missing with function constructors.

```javascript
class Person {
    //~ constructor () {
        //~ this = Object.create(new.target.prototype);
        //~ return this;
    //~ }
}
//~ Person.prototype = { constructor: Person };

class User extends Person {
    constructor (name) {
        super(); // translates to:
        //~ this = new Object.getPrototypeOf(User);

        this.name = name;
        //~ return this;
    }
}
//~ User.prototype = Object.create(Person.prototype);
//~ User.prototype.constructor = User;
//~ Object.setPrototypeOf(User, Person);

```

Starting at the bottom, you can see the extending code is set up automatically. In addition to setting up the prototype chain, it also includes setting up static inheritance by having the constructor inherit directly from the constructor it’s extending.

Inside the constructor, when `super()` is called, a call is made to the constructor that the current constructor inherits from, which in this case would be `Parent`. This happens dynamically so it’s possible that it would not be the same constructor in the `extends` clause (only if you, or someone else, was messing around changing static inheritance before construction). In either case, as seen in the `Person` constructor, the object created is created with a prototype based on the `new.target` which is the function that `new` was called with, or in this case `User`. The actual object instance creation step only happens in the base class, or the last class in the super chain. Every other superclass that would be in between would get their instance from their own `super()` call until eventually reaching the `new.target` class which, in turn, ultimately passes it back to the caller.

It’s all this extra work that makes `class` syntax much more appealing when defining constructors. All of the boilerplate code that you had to do before, notably when extending, is taken care of for you.

Theres a bit more magic with constructors not touched upon here. That includes (but may not be limited to):

- For any constructor, if you return explicitly out of a constructor, as long as you’re returning an object, the automatic `this` return is ignored.
- `class` constructors throw an error if you attempt to call them as a function. This is a little different than adding a `throw` in the constructor itself (purposefully not included in code examples above) since this error would happen before the constructor is ever run.
- if a `constructor` method isn’t defined for a `class`, one is created for you automatically, `constructor(){}` if not extending another class and `constructor(...args){ super(...args); }` if it is.
- Only `class` constructors can properly extend builtins that allow created instances to be exotic if necessary (e.g. extending Array) and have all of their necessary internal slots initialized.

More info:

- [Functions on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions)
- [constructor on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor)
- [Classes on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
