3

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?

  • 1
    The library is converted to ES5 (ES3?): https://github.com/facebook/immutable-js/blob/c0308e7944956c2e3d5afe6c80a4869a92980f11/dist/immutable.js#L2899 – Felix Kling Sep 09 '17 at 01:53

2 Answers2

3

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.

czerny
  • 15,090
  • 14
  • 68
  • 96
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
  • fun fun function has a series on objects and illustrates `Object.assign()` and `Object.create()` if you want to understand them better. These and function factories are very near to my heart along with node.js. – agm1984 Sep 09 '17 at 02:48
  • I can't give you a slick answer, but I know Object.create() basically creates a reference to another object's prototypes, but it does something like not "fully" create it, so it has some bearing on increased memory performance. Other people can tighten up that definition for you. – agm1984 Sep 09 '17 at 02:50
1

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.

Nickolay
  • 31,095
  • 13
  • 107
  • 185