391

Javascript 1.9.3 / ECMAScript 5 introduces Object.create, which Douglas Crockford amongst others has been advocating for a long time. How do I replace new in the code below with Object.create?

var UserA = function(nameParam) {
    this.id = MY_GLOBAL.nextId();
    this.name = nameParam;
}
UserA.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();

(Assume MY_GLOBAL.nextId exists).

The best I can come up with is:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();

There doesn't seem to be any advantage, so I think I'm not getting it. I'm probably being too neo-classical. How should I use Object.create to create user 'bob'?

Yves M.
  • 29,855
  • 23
  • 108
  • 144
Graham King
  • 5,710
  • 3
  • 25
  • 23
  • When the accepted answer has less votes than the question, maybe the accepted answer isn't acceptable? @CMS would have you write a factory function that uses `Object.create` internally to get the same single-step functionality as `new UserA('bob');`. – Rick Jolly Jun 01 '13 at 17:40
  • 1
    Perhaps its the *most* acceptable answer, considering it has the most votes of all 6 answers. – Cory Gross Jul 27 '13 at 08:27
  • 3
    See also [Understanding the difference between Object.create() and new SomeFunction()](http://stackoverflow.com/q/4166616/1048572) – Bergi Jul 24 '15 at 15:04
  • 1
    Crockford was an early guiding sage in the JS world, but his heyday is past. His suggestion to stop using `new` altogether never caught on, even though `Object.create` is useful in other ways. – Andy Apr 21 '17 at 17:22
  • @Andy the reason for this relies on the paradigm you use. If you use functional programming in JS you prefer Object.create rather than new keyword. – Anastasis Nov 19 '19 at 14:52

15 Answers15

267

With only one level of inheritance, your example may not let you see the real benefits of Object.create.

This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.

On your userB example, I don't think that your init method should be public or even exist, if you call again this method on an existing object instance, the id and name properties will change.

Object.create lets you initialize object properties using its second argument, e.g.:

var userB = {
  sayHello: function() {
    console.log('Hello '+ this.name);
  }
};

var bob = Object.create(userB, {
  'id' : {
    value: MY_GLOBAL.nextId(),
    enumerable:true // writable:false, configurable(deletable):false by default
  },
  'name': {
    value: 'Bob',
    enumerable: true
  }
});

As you can see, the properties can be initialized on the second argument of Object.create, with an object literal using a syntax similar to the used by the Object.defineProperties and Object.defineProperty methods.

It lets you set the property attributes (enumerable, writable, or configurable), which can be really useful.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 11
    1. Thanks for the pointer to differential inheritance. 2. Does this mean no more constructors? I need to remember to set 'id' to MY_GLOBAL.nextId() every time I create a user? – Graham King Apr 25 '10 at 22:02
  • 4
    You're welcome @Graham, you're right, no more constructors needed with this method, although the currently available implementations on Firefox 3.7apre5, the latest WebKit Nightly builds and Chrome 5 Beta, are [not so fast](http://webreflection.blogspot.com/2010/03/new-constructor-vs-objectcreate.html) compared with plain old constructors, hopefully this will change in the near future. For the object creation, you could create a *factory* function(i.e. `function createUser(name) { ... }`, with all the needed logic to create your user objects within with `Object.create`. – Christian C. Salvadó Apr 26 '10 at 01:07
  • 5
    Re: no more constructors: Normally you'd write an ordinary function to be the "factory" for objects. Internally it would use `Object.create` to make a blank object, and then modify it as necessary before returning it. The caller of that factory doesn't have to remember the prefix `new`. – Daniel Earwicker Jul 27 '11 at 09:11
  • @CMS When would or wouldn't you want to set enumerable to true? – ryanve Jan 27 '12 at 19:23
  • 2
    @GrahamKing You could use a closure to init your objects: http://jsfiddle.net/Prqdt/ – amiuhle Jun 25 '12 at 14:31
  • @CMS What is *differential inheritance*?Why is it called so? – Geek Jul 13 '13 at 10:13
  • @CMS ", if you call again this method on an existing object instance, the id and name properties will change.". Wait, how? `this` is referring to the new object with its own name and id properties. Why would calling `init` on an different object with the same prototype change those properties? – linstantnoodles Apr 23 '14 at 01:02
  • Passing in the 2nd param a properties object does not initialize the new object to have those properties. I have to set them directly, line by line. var model = Object.create(parent); model.someFunction = someFunction; function someFunction(){...} – Skystrider Sep 30 '15 at 19:46
  • it is not inheritance, it is object composition – albanx Apr 29 '17 at 15:35
  • 1
    @ryanve when the object has some private property that you don't want to be enumerated (e.g. in a `for in` where you don't want to list object metadata but just actual data properties). See [MDN Enumerability](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) – Kamafeather Sep 30 '19 at 21:23
  • @Geek see [Differential Inheritance on Wikipedia](https://en.wikipedia.org/wiki/Differential_inheritance) – Kamafeather Sep 30 '19 at 21:25
  • @linstantnoodles he didn't write "different object" but "existing"; I think the emphasis is on "again", since the *public* `init` method replaces the (kind of private) `constructor`, but might be called multiple times and cause undesired results; initialisation should happen just once. – Kamafeather Sep 30 '19 at 21:37
56

There is really no advantage in using Object.create(...) over new object.

Those advocating this method generally state rather ambiguous advantages: "scalability", or "more natural to JavaScript" etc.

However, I have yet to see a concrete example that shows that Object.create has any advantages over using new. On the contrary there are known problems with it. Sam Elsamman describes what happens when there are nested objects and Object.create(...) is used:

var Animal = {
    traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!

This occurs because Object.create(...) advocates a practice where data is used to create new objects; here the Animal datum becomes part of the prototype of lion and bird, and causes problems as it is shared. When using new the prototypal inheritance is explicit:

function Animal() {
    this.traits = {};
}

function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();

var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4

Regarding, the optional property attributes that are passed into Object.create(...), these can be added using Object.defineProperties(...).

7ochem
  • 2,183
  • 1
  • 34
  • 42
  • 26
    I disagree. `Object.create` neither enforces nor encourages the practice of using prototypes as any kind of "storage for default data values" as the linked article seems to suggest. Proper data initialization is the responsibility of whoever creates a particular object (like a factory or builder in the OO design). *(Inheriting data rather than behaviour is feasible in JS, but not a common scenario.)* – Kos Nov 14 '12 at 12:54
  • 43
    As long as you understand that the argument to Object.create is supposed to be the prototype, this problem shouldn't come up. Obviously you can get the same bad behavior when using **new** if you say Animal.prototype.traits = {}; The only reason it's clear you shouldn't do that is that you understand how javascript prototypes work. – plediii Jan 03 '13 at 19:48
  • 21
    God god! So many downvotes for providing the right answer :-) The point is Object.create does not permit a mechanism for constructor arguments so one is forced to extend "data". Now this data may contain nested objects, which leads to the problem above. With prototypal inheritance on the other hand we only run into this problem if we were to _explicitly_ write out `Animal.prototype.traits = {};`. One method is implicit the other explicit. Don't chose the one that leads to problems. – Zephyr was a Friend of Mine Jun 16 '13 at 10:14
  • 1
    In the second example, the two objects don't share the common prototype (although they do share the next one in the chain). If you want both animals to have their own traits property, you could apply the Animal function to both bird and lion, and they will each get a traits property directly (no prototype, and not shared). There may times when you want things to be shared (like you don't want to recreate all the functions each time a new object is created), and I think that is when you make use of the prototype. – zod Jul 04 '13 at 14:38
  • 1
    Problem with using `new` with a subtype this way is that you never want to specify arguments for the supertype ctor, since you don't have the data at this point. Suddenly you need to insert a conditional in your supertype ctor to check if the arguments are provided or not; but what if you don't want a default ctor? There is no way that I know of to determine whether the call was done to setup the prototype of a subtype or to setup the data of the supertype in the subtype ctor. – tne Oct 03 '13 at 10:45
  • 6
    [Please see this post](http://stackoverflow.com/questions/3191103/javascript-object-create-inheriting-nested-properties) for a simple solution to the 2 legged lion. [Here's some working code to illustrate it](http://jsfiddle.net/d131/a6xhu/) – d13 Oct 31 '13 at 02:42
  • 12
    I would suggest reading this article by Kyle Simpson. All three parts are interesting, but part 3 is key. If after reading those you still think "new" is better than Object.create(), then there is no hope for you! :) http://davidwalsh.name/javascript-objects-deconstruction – MindJuice Jun 18 '14 at 17:12
  • 3
    To be fair, the second example should be completed so: `var clarence = new Lion(); clarence.traits.legs = 3; console.log(lion.traits.legs) // 3, shit!` – rixo Oct 23 '15 at 23:51
  • 4
    If you were using Object.create with the proper conceptual understanding of prototypes, you would say "Of course it doesn't work that way! The shared prototype is a feature, not a bug!" – Mehdi Maujood Mar 09 '16 at 20:47
  • To clarify, we can share multiple methods from multiple prototype objects with the help of Object.Create. This sharing flexibility is clearly an "advantage" over new, and part of the beauty of JavaScript. – klewis Mar 02 '18 at 15:51
  • 5
    What javascript proves is that if you build the foundations out of crap, all subsequent layers of the house will also be crap. – Adamantus Mar 01 '19 at 22:01
42

Object.create is not yet standard on several browsers, for example IE8, Opera v11.5, Konq 4.3 do not have it. You can use Douglas Crockford's version of Object.create for those browsers but this doesn't include the second 'initialisation object' parameter used in CMS's answer.

For cross browser code one way to get object initialisation in the meantime is to customise Crockford's Object.create. Here is one method:-

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}

This maintains Crockford prototypal inheritance, and also checks for any init method in the object, then runs it with your parameter(s), like say new man('John','Smith'). Your code then becomes:-

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();

So bob inherits the sayHello method and now has own properties id=1 and name='Bob'. These properties are both writable and enumerable of course. This is also a much simpler way to initialise than for ECMA Object.create especially if you aren't concerned about the writable, enumerable and configurable attributes.

For initialisation without an init method the following Crockford mod could be used:-

Object.gen = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

This fills the userB own properties, in the order they are defined, using the Object.gen parameters from left to right after the userB parameter. It uses the for(prop in o) loop so, by ECMA standards, the order of property enumeration cannot be guaranteed the same as the order of property definition. However, several code examples tested on (4) major browsers show they are the same, provided the hasOwnProperty filter is used, and sometimes even if not.

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}};  // For example

var userB = {
   name: null,
   id: null,
   sayHello: function() {
      console.log('Hello '+ this.name);
   }
}

var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());

Somewhat simpler I would say than Object.build since userB does not need an init method. Also userB is not specifically a constructor but looks like a normal singleton object. So with this method you can construct and initialise from normal plain objects.

outis
  • 75,655
  • 22
  • 151
  • 221
John
  • 445
  • 4
  • 2
  • 4
    There is a polyfill for `Object.create` in the ES5 Shim https://github.com/kriskowal/es5-shim – ryanve Jan 27 '12 at 19:19
  • Great article! I've added a [JSFiddle](http://jsfiddle.net/AV7sV/), so you have a working example for both Object.build and Object.gen in one file. Also, I've added some semicolons which were missing (available in JSFiddle only). – Matt Aug 13 '13 at 11:31
28

TL;DR:

new Computer() will invoke the constructor function Computer(){} for one time, while Object.create(Computer.prototype) won't.

All the advantages are based on this point.

Sidenote about performance: Constructor invoking like new Computer() is heavily optimized by the engine, so it may be even faster than Object.create.

NamiW
  • 1,572
  • 4
  • 19
  • 33
14

You could make the init method return this, and then chain the calls together, like this:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
        return this;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};

var bob = Object.create(userB).init('Bob');
samfrances
  • 3,405
  • 3
  • 25
  • 40
  • One can further do `create = Object.create.bind(Object); log = console.log.bind(console)` and then one can just write `create(...)` and `log(...)`. See [here](https://stackoverflow.com/a/10115970/1658543) for what `.bind(...)` does. – Nils Lindemann Dec 18 '21 at 18:21
10

Another possible usage of Object.create is to clone immutable objects in a cheap and effective way.

var anObj = {
    a: "test",
    b: "jest"
};

var bObj = Object.create(anObj);

bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj

// now bObj is {a: test, b: gone, c: brand}

Notes: The above snippet creates a clone of an source object (aka not a reference, as in cObj = aObj). It benefits over the copy-properties method (see 1), in that it does not copy object member properties. Rather it creates another -destination- object with it's prototype set on the source object. Moreover when properties are modified on the dest object, they are created "on the fly", masking the prototype's (src's) properties.This constitutes a fast an effective way of cloning immutable objects.

The caveat here is that this applies to source objects that should not be modified after creation (immutable). If the source object is modified after creation, all the clone's unmasked properties will be modified, too.

Fiddle here(http://jsfiddle.net/y5b5q/1/) (needs Object.create capable browser).

basos
  • 578
  • 4
  • 11
  • 7
    Calling this clone is confusing to me (and probably many others). To most people a `clone` method implies that changes to the original would not affect the clone. – kybernetikos Sep 26 '12 at 13:56
  • Understood, I amended the answer to account only for source objects considered immutable. – basos Dec 24 '12 at 12:58
  • Cloning objects repeatedly this way will quickly get you into trouble, as you'll have an object with a really long prototype chain that keeps all those old objects in memory. I'll sometimes use `Object.create` in testing to make mocks that override some properties of an *instance* of a class while keeping others the same. But I rarely use it. – Andy Apr 21 '17 at 17:27
  • I checked the above code and may be `Object.create` has evolved but for now `Object.create` is not cloning anything and the result of the code `var bObj = Object.create(anObj); console.log(bObj);` is `{}` means no properties are copied. – dev_khan Nov 22 '19 at 07:10
7

I think the main point in question - is to understand difference between new and Object.create approaches. Accordingly to this answer and to this video new keyword does next things:

  1. Creates new object.

  2. Links new object to constructor function (prototype).

  3. Makes this variable point to the new object.

  4. Executes constructor function using the new object and implicit perform return this;

  5. Assigns constructor function name to new object's property constructor.

Object.create performs only 1st and 2nd steps!!!

In code example provided in question it isn't big deal, but in next example it is:

var onlineUsers = [];
function SiteMember(name) {
    this.name = name;
    onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
    return this.name;
}
function Guest(name) {
    SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();

var g = new Guest('James');
console.log(onlineUsers);

As side effect result will be:

[ undefined, 'James' ]

because of Guest.prototype = new SiteMember();
But we don't need to execute parent constructor method, we need only make method getName to be available in Guest. Hence we have to use Object.create.
If replace Guest.prototype = new SiteMember();
to Guest.prototype = Object.create(SiteMember.prototype); result be:

[ 'James' ]
cn007b
  • 16,596
  • 7
  • 59
  • 74
  • This is bad example of using Object,create to solve combination inheritance (constructor stealing + prototype chaining) major failing which is that parent constructor is called twice. Object.create creates new object using existing object as prototype which means one more prototype in the chain. The mentioned failing is solved using parasitic combination inheritance (constructor stealing + hybrid prototype chaining). We only need to copy parent prototype and it can be done like this: var prototype = new Object(SiteMember.prototype); prototype.constructor = Guest; Guest.prototype = prototype; – Dalibor Nov 30 '19 at 23:59
6

Sometimes you cannot create an object with NEW but are still able to invoke the CREATE method.

For example: if you want to define a Custom Element it must derive from HTMLElement.

proto = new HTMLElement  //fail :(
proto = Object.create( HTMLElement.prototype )  //OK :)
document.registerElement( "custom-element", { prototype: proto } )
Supersharp
  • 29,002
  • 9
  • 92
  • 134
4

The advantage is that Object.create is typically slower than new on most browsers

In this jsperf example, in a Chromium, browser new is 30 times as fast as Object.create(obj) although both are pretty fast. This is all pretty strange because new does more things (like invoking a constructor) where Object.create should be just creating a new Object with the passed in object as a prototype (secret link in Crockford-speak)

Perhaps the browsers have not caught up in making Object.create more efficient (perhaps they are basing it on new under the covers ... even in native code)

frooble
  • 155
  • 1
  • 5
4

Summary:

  • Object.create() is a Javascript function which takes 2 arguments and returns a new object.
  • The first argument is an object which will be the prototype of the newly created object
  • The second argument is an object which will be the properties of the newly created object

Example:

const proto = {
  talk : () => console.log('hi')
}

const props = {
  age: {
    writable: true,
    configurable: true,
    value: 26
  }
}


let Person = Object.create(proto, props)

console.log(Person.age);
Person.talk();

Practical applications:

  1. The main advantage of creating an object in this manner is that the prototype can be explicitly defined. When using an object literal, or the new keyword you have no control over this (however, you can overwrite them of course).
  2. If we want to have a prototype The new keyword invokes a constructor function. With Object.create() there is no need for invoking or even declaring a constructor function.
  3. It can Basically be a helpful tool when you want create objects in a very dynamic manner. We can make an object factory function which creates objects with different prototypes depending on the arguments received.
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
3

You have to make a custom Object.create() function. One that addresses Crockfords concerns and also calls your init function.

This will work:

var userBPrototype = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};


function UserB(name) {
    function F() {};
    F.prototype = userBPrototype;
    var f = new F;
    f.init(name);
    return f;
}

var bob = UserB('bob');
bob.sayHello();

Here UserB is like Object.create, but adjusted for our needs.

If you want, you can also call:

var bob = new UserB('bob');
edwin
  • 2,643
  • 20
  • 17
3

While Douglas Crockford used to be a zealous advocate of Object.create() and he is basically the reason why this construct actually is in javascript, he no longer has this opinion.

He stopped using Object.create, because he stopped using this keyword altogether as it causes too much trouble. For example, if you are not careful it can easily point to the global object, which can have really bad consequences. And he claims that without using this Object.create does not make sense anymore.

You can check this video from 2014 where he talks at Nordic.js:

https://www.youtube.com/watch?v=PSGEjv3Tqo0

enter image description here

Vojtech Ruzicka
  • 16,384
  • 15
  • 63
  • 66
3

new and Object.create serve different purposes. new is intended to create a new instance of an object type. Object.create is intended to simply create a new object and set its prototype. Why is this useful? To implement inheritance without accessing the __proto__ property. An object instance's prototype referred to as [[Prototype]] is an internal property of the virtual machine and is not intended to be directly accessed. The only reason it is actually possible to directly access [[Prototype]] as the __proto__ property is because it has always been a de-facto standard of every major virtual machine's implementation of ECMAScript, and at this point removing it would break a lot of existing code.

In response to the answer above by 7ochem, objects should absolutely never have their prototype set to the result of a new statement, not only because there's no point calling the same prototype constructor multiple times but also because two instances of the same class can end up with different behavior if one's prototype is modified after being created. Both examples are simply bad code as a result of misunderstanding and breaking the intended behavior of the prototype inheritance chain.

Instead of accessing __proto__, an instance's prototype should be written to when an it is created with Object.create or afterward with Object.setPrototypeOf, and read with Object.getPrototypeOf or Object.isPrototypeOf.

Also, as the Mozilla documentation of Object.setPrototypeOf points out, it is a bad idea to modify the prototype of an object after it is created for performance reasons, in addition to the fact that modifying an object's prototype after it is created can cause undefined behavior if a given piece of code that accesses it can be executed before OR after the prototype is modified, unless that code is very careful to check the current prototype or not access any property that differs between the two.

Given

const X = function (v) { this.v = v }; X.prototype.whatAmI = 'X'; X.prototype.getWhatIAm = () => this.whatAmI; X.prototype.getV = () => this.v;

the following VM pseudo-code is equivalent to the statement const x0 = new X(1);:

const x0 = {}; x0.[[Prototype]] = X.prototype; X.prototype.constructor.call(x0, 1);

Note although the constructor can return any value, the new statement always ignores its return value and returns a reference to the newly created object.

And the following pseudo-code is equivalent to the statement const x1 = Object.create(X.prototype);:

const x0 = {}; x0.[[Prototype]] = X.prototype;

As you can see, the only difference between the two is that Object.create does not execute the constructor, which can actually return any value but simply returns the new object reference this if not otherwise specified.

Now, if we wanted to create a subclass Y with the following definition:

const Y = function(u) { this.u = u; } Y.prototype.whatAmI = 'Y'; Y.prototype.getU = () => this.u;

Then we can make it inherit from X like this by writing to __proto__:

Y.prototype.__proto__ = X.prototype;

While the same thing could be accomplished without ever writing to __proto__ with:

Y.prototype = Object.create(X.prototype); Y.prototype.constructor = Y;

In the latter case, it is necessary to set the constructor property of the prototype so that the correct constructor is called by the new Y statement, otherwise new Y will call the function X. If the programmer does want new Y to call X, it would be more properly done in Y's constructor with X.call(this, u)

paulyc
  • 31
  • 4
3

new Operator

  • This is used to create object from a constructor function
  • The new keywords also executes the constructor function
function Car() {
  console.log(this) // this points to myCar
  this.name = "Honda";
}

var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object

Object.create

  • You can also use Object.create to create a new object
  • But, it does not execute the constructor function
  • Object.create is used to create an object from another object
const Car = {
  name: "Honda"
}

var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // object

Shardul
  • 984
  • 1
  • 12
  • 19
2

I prefer a closure approach.

I still use new. I don't use Object.create. I don't use this.

I still use new as I like the declarative nature of it.

Consider this for simple inheritance.

window.Quad = (function() {

    function Quad() {

        const wheels = 4;
        const drivingWheels = 2;

        let motorSize = 0;

        function setMotorSize(_) {
            motorSize = _;
        }

        function getMotorSize() {
            return motorSize;
        }

        function getWheelCount() {
            return wheels;
        }

        function getDrivingWheelCount() {
            return drivingWheels;
        }
        return Object.freeze({
            getWheelCount,
            getDrivingWheelCount,
            getMotorSize,
            setMotorSize
        });
    }

    return Object.freeze(Quad);
})();

window.Car4wd = (function() {

    function Car4wd() {
        const quad = new Quad();

        const spareWheels = 1;
        const extraDrivingWheels = 2;

        function getSpareWheelCount() {
            return spareWheels;
        }

        function getDrivingWheelCount() {
            return quad.getDrivingWheelCount() + extraDrivingWheels;
        }

        return Object.freeze(Object.assign({}, quad, {
            getSpareWheelCount,
            getDrivingWheelCount
        }));
    }

    return Object.freeze(Car4wd);
})();

let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1

Feedback encouraged.

p0wdr.com
  • 307
  • 2
  • 4
  • 1
    This is intriguing. Could you extend the example to show how you would implement setters? Or would Object.freeze() prevent that? – jk7 Apr 03 '19 at 17:42
  • 1
    The freeze is just stopping the runtime modification of the "class". I've extended the example of the parent with a local variable in the closure and a getter and setter to show managing the "private" variable in the closure – p0wdr.com Apr 04 '19 at 21:14
  • Re Feedback, can you give code that creates an instance please? I feel like this is 'server' code and that no 'client' code has been given. – S Meaden Jun 03 '21 at 13:08
  • The instance creation happens at the end of the example with the following lines let myQuad = new Quad(); let myCar = new Car4wd(); this is client code, it uses the window object to store the types/classes – p0wdr.com Oct 18 '21 at 22:38