I am trying to work out how to instantiate a new object from another instantiated object without without using the new operator. The following code below works but I hear the __proto__ property is depreciated.
var MyObject = function( arg ) {
this.value = arg;
};
MyObject.prototype.getValue = function() {
return this.value;
};
// Standard way of instantiating an object
var object1 = new MyObject( 'foo' );
// Creating new object based on another without using new operator
var object2 = {};
object2.__proto__ = object1.__proto__
object1.constructor.call( object2, 'bar' );
console.log( object1 );
console.log( object2 );
So how would I do this without the __proto__ property?
Quoting from __proto__
's MDN Docs,
The
__proto__
property is deprecated and should not be used.Object.getPrototypeOf
should be used instead of the__proto__
getter to determine the [[Prototype]] of an object. Mutating the [[Prototype]] of an object, no matter how this is accomplished, is strongly discouraged, because it is very slow and unavoidably slows down subsequent execution in modern JavaScript implementations. However,Object.setPrototypeOf
is provided in ES6 as a very-slightly-preferred alternative to the__proto__
setter.
But your actual code works, let us see why.
First of all, any object which is created with an Object literal will have its __proto__
property as the same as Object.prototype
. You can check this like this
var object2 = {};
console.log(object2.__proto__ === Object.prototype);
# true
Since object1
is created with MyObject
function, the following is true
console.log(object1.__proto__ === MyObject.prototype);
# true
When you say
object2.__proto__ = object1.__proto__;
From 2, we can see that it is the same as,
object2.__proto__ = MyObject.prototype;
so, you are just making JavaScript believe that, object2
is also an object of MyObject
.
Since we assigned MyObject
's prototype to object1
's prototype, constructor
of both the objects are the same
console.log(object1.constructor === object2.constructor);
And then you are calling the MyObject
function with object2
as this
.
object1.constructor.call( object2, 'bar' );
Since changing __proto__
is NOT recommended, the best way to do this would be to use new
keyword only
var object1 = new MyObject('foo'),
object2 = new MyObject('bar');
But, lets say you have got only object1
, but not the definition of MyObject
. Then, you can make use of the constructor
property like this
object2 = new object1.constructor('bar');
As thefourtheye mentioned, changing the [[Prototype]] of an object after it is created is strongly discourged.
However, in your use case you don't really have a reason to change the [[Prototype]] at a random point in an object's lifetime, but instead you want to create an object with a given [[Prototype]].
The method that accomplishes this is Object.create
, which creates an object with a specified [[Prototype]] value:
var object2 = Object.create(object1);
object1.constructor.call(object2, 'bar');
If your desired environment doesn't support Object.create, a shim is available on the MDN page. While imperfect (not all functionality is covered), the shim does exactly what you need in this scenario.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With