CodeMarmoset
CodeMarmoset

Reputation: 45

How does Immutable.js omit the new keyword?

So, an ES6 syntax puzzle. As far as I can see if you create a javascript class for example: DragonSlayer then to create an instance of that class you need to use the 'new' keyword.

let girl = new DragonSlayer();

If you don't want to use the 'new' keyword you can create a wrapper function.

function ADragonSlayer () {
    return new DragonSlayer() }

let girl = ADragonSlayer();

So can anyone explain to me how the Immutable.js library works?

That seems to create a class called List, then export an object with that class as a same-named property (which you get via destructuring during import). Yet to create an instance you can just call the function with no new at all.

const { List } = require('immutable')

let newList = List();

I've foraged around in the source code but so far been unable to get a handle on how such black magic has been architected. Anyone have some pointers?

Upvotes: 3

Views: 740

Answers (2)

Patrick Evans
Patrick Evans

Reputation: 42736

It utilizes Object.create

In the constructor you will see it will either return back:

  1. The value passed
  2. empty which is a value returned from emptyList() which calls makeList()
  3. Or a value returned directly from a makeList() call.

Inside makeList() is a call to Object.create() which creates a new object from the prototype that is passed

https://github.com/facebook/immutable-js/blob/d960d5c4e00f616aa2aec0ecd765735525c6166f/src/List.js#L407

const list = Object.create(ListPrototype);

This is ultimately what is returned when you call List()

There is another question here that asks about the use of Object.create instead of new.

Upvotes: 3

Nickolay
Nickolay

Reputation: 32063

You're right that classes can't be instantiated without new:

class List {}; List()
// TypeError: class constructors must be invoked with |new|

However you probably require the compiled version of immutable.js, in which the class declaration is compiled down to:

var List = (function (IndexedCollection$$1) {
  function List(value) {
    // ...
   return empty.withMutations(function (list) {
  }
  // ...
  return List;
}(...))

...which can be called without new.

Upvotes: 1

Related Questions