JavaScript constructor alternative

Since it is not possible to use the new operator with an array of arguments (.call or .apply), I wonder if I can do this manually.

In the following code, are the equivalents of obj1 and obj2 equivalent (in ES3)?

 function MyClass(a, b, c) {} var obj1 = new MyClass(2,3,4) var tmp = function() {} tmp.prototype = MyClass.prototype; var obj2 = new tmp; obj2.constructor = MyClass; MyClass.call(obj2, 2,3,4); 

- edit1 -

Do you know your answers that the above code is incorrect or not equivalent to the construction of the object?

+4
source share
4 answers

Using the following syntax, you should be able to apply / invoke the constructor directly, not too much fluff. Or create an instance without using the new operator.

 function MyClass(a,b,c){ if (!(this instanceof MyClass)){ return new MyClass(a,b,c) } // to demonstrate the arguments are usable using call/apply this.arg1 = a; this.arg2 = b; this.arg3 = c; } var obj2 = MyClass.call(null,1,2,3); // or MyClass.apply(null,[1,2,3]) alert([obj2.arg1,obj2.arg2,obj2.arg3].join(',')); //=> 1,2,3 
+1
source

How about this:

 var o = new MyClass; MyClass.apply(o, args); 

By creating an object that is properly inherited from the prototype through the new keyword, you again call the constructor on this object with your parameters.

All this requires that your constructor be well-formed, do not crash about null parameters and have no side effects when called more than once on the same object. Of course, all these conditions are true because you are writing the correct units, right?

To answer your real question if you add

tmp.prototype.constructor = MyClass

then yes obj1 and obj2 are "the same."

+1
source

If you are using ES5, you can do it right with Object.create() :

 function MyClass(a) { console.log('in constructor with param: ' + a); this.foo = a; } var a = new MyClass('a'); var b = Object.create(MyClass.prototype); b.constructor.apply(b, ['b']); console.log('a.foo = ', a.foo, ', b.foo = ', b.foo); console.log(b instanceof MyClass); 

output:

 in constructor with param: a in constructor with param: b a.foo = a , b.foo = b true 

See http://jsfiddle.net/Qjfyt/1/ , which shows that the constructor is only called once once, as expected.

+1
source

Well, you can use apply and get an object that looks almost exactly like an instance with such a new one:

 function MyClass(a, b, c) {this.foo = a;} var a, b = {}, args = [2, 3, 4]; // notice that b is an Object! a = new MyClass(2,3,4); MyClass.prototype.constructor.apply(b, [2, 3, 4]); console.log('a.foo', a.foo, 'b.foo', b.foo); 

As you will see, they are equivalent, but if you specify:

 console.log('b.constructor === a.constructor', b.constructor === a.constructor); 

They do not have the same constructor. This is because b was originally an instance of "Object" because it was installed in the object literal and used as the context for applying the MyClass prototype to the constructor. They will have the same attributes / methods, so maybe this is good enough for your needs?

EDIT: see @Raynos comment below. This method means that you lose everything that is defined using MyClass.prototype.

0
source

Source: https://habr.com/ru/post/1346947/


All Articles