Shorthand for Object.create() with multiple properties

If I want to create an object in JavaScript that has a prototype link to another object, but has several of it's own properties how can I do this?

var object1 = {
  a: 1,
  b: 2
};

var object2 = Object.create( object1 );
object2.c = 3;
object2.d = 4;

console.log( object2 ); // my new object with object1 as it's prototype link

My challenge here is that I have to set object2's properties one at a time.

My other option is:

var object1 = {
  a: 1,
  b: 2
};

var object2 = {
  c: 3,
  d: 4
};
    
Object.setPrototypeOf( object2, object1 );

console.log( object2 );

My challenge above is that the performance is supposed to be terrible. Namely, setPrototypeOf is slow. https://jsperf.com/object-create-vs-object-setprototypeof

And then of course, there's the "shorthand" where you provide, writeable, enumerable and all that to Object.create(), but that's not really shorthand.

Any ideas?


Solution 1:

You can combine Object.create with Object.assign for this:

var object2 = Object.assign(Object.create(object1), {
    c: 3,
    d: 4
});

Solution 2:

As an alternative to Object.assign, remember Object.create accepts a second argument with the property descriptors you want to add to the object:

var object1 = {
  a: 1,
  b: 2
};
var object2 = Object.create(object1, {
  c: {value: 3, enumerable: true},
  d: {value: 4, enumerable: true}
});
console.log( object2 ); // my new object with object1 as it's prototype link

Note the default is non-configurable, non-writable and non-enumerable.

If that's a problem, ES2017 introduces Object.getOwnPropertyDescriptors.

var object1 = {
  a: 1,
  b: 2
};
var object2 = Object.create(object1, Object.getOwnPropertyDescriptors({
  c: 3,
  d: 4
}));
console.log( object2 ); // my new object with object1 as it's prototype link

Solution 3:

Normally, when we talk about setting and swapping prototypes, we are talking about constructor functions that are instantiated into objects and not object literals themselves.

You can certainly, just manually switch the prototype yourself in this case (which is the basis for prototypical inheritance) and will cause you to inherit the right properties, but you also now have to deal with constructor issues when instances of your derived object get made.

But, this technique is fast as it only requires a new instance to be made and that reference is then set in the prototype property.

function object1(){
  this.a = 1;
  this.b = 2;
  console.log("object1 has been invoked");
};

function object2(){
  console.log("object2 has been invoked");
  this.c = 3;
  this.d = 4;
};
    
// It's very important that the prototype be set to a NEW instance
// of the super-object so that you don't wind up sharing a prototype
// with other unintended objects.
object2.prototype = new object1();

// object2.prototype.constructor was the function object2
// But now that object2 has had its prototype swapped out
// to object1, when new instances of object2 are made, the
// constructor for object1 will execute. To fix this, we
// just need to reset the constructor property of the new
// prototype that we just set. That's another reason we created
// a new instance of object1, so we could modify the constructor
// of that instance without screwing up other instances of object1
// that may be in use. object2 will use object1 as 
// it's prototype, but that particular instance of object1
// will have object2 set as the constructor to use when instances
// are needed.
object2.prototype.constructor = object2;

console.log( new object2() );