How can I call a javascript constructor using call or apply? [duplicate] How can I call a javascript constructor using call or apply? [duplicate] javascript javascript

How can I call a javascript constructor using call or apply? [duplicate]


This is how you do it:

function applyToConstructor(constructor, argArray) {    var args = [null].concat(argArray);    var factoryFunction = constructor.bind.apply(constructor, args);    return new factoryFunction();}var d = applyToConstructor(Date, [2008, 10, 8, 00, 16, 34, 254]);

Call is slightly easier

function callConstructor(constructor) {    var factoryFunction = constructor.bind.apply(constructor, arguments);    return new factoryFunction();}var d = callConstructor(Date, 2008, 10, 8, 00, 16, 34, 254);

You can use either of these to create factory functions:

var dateFactory = applyToConstructor.bind(null, Date)var d = dateFactory([2008, 10, 8, 00, 16, 34, 254]);

or

var dateFactory = callConstructor.bind(null, Date)var d = dateFactory(2008, 10, 8, 00, 16, 34, 254);

It will work with any constructor, not just built-ins or constructors that can double as functions (like Date).

However it does require the Ecmascript 5 .bind function. Shims will probably not work correctly.

A different approach, more in the style of some of the other answers is to create a function version of the built in new. This will not work on all builtins (like Date).

function neu(constructor) {    // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.2    var instance = Object.create(constructor.prototype);    var result = constructor.apply(instance, Array.prototype.slice.call(arguments, 1));    // The ECMAScript language types are Undefined, Null, Boolean, String, Number, and Object.    return (result !== null && typeof result === 'object') ? result : instance;}function Person(first, last) {this.first = first;this.last = last};Person.prototype.hi = function(){console.log(this.first, this.last);};var p = neu(Person, "Neo", "Anderson");

And now, of course you can do .apply or .call or .bind on neu as normal.

For example:

var personFactory = neu.bind(null, Person);var d = personFactory("Harry", "Potter");

I feel that the first solution I give is better though, as it doesn't depend on you correctly replicating the semantics of a builtin and it works correctly with builtins.


Try this:

function conthunktor(Constructor) {    var args = Array.prototype.slice.call(arguments, 1);    return function() {         var Temp = function(){}, // temporary constructor             inst, ret; // other vars         // Give the Temp constructor the Constructor's prototype         Temp.prototype = Constructor.prototype;         // Create a new instance         inst = new Temp;         // Call the original Constructor with the temp         // instance as its context (i.e. its 'this' value)         ret = Constructor.apply(inst, args);         // If an object has been returned then return it otherwise         // return the original instance.         // (consistent with behaviour of the new operator)         return Object(ret) === ret ? ret : inst;    }}


This function is identical to new in all cases. It will probably be significantly slower than 999’s answer, though, so use it only if you really need it.

function applyConstructor(ctor, args) {    var a = [];    for (var i = 0; i < args.length; i++)        a[i] = 'args[' + i + ']';    return eval('new ctor(' + a.join() + ')');}

UPDATE: Once ES6 support is widespread, you'll be able to write this:

function applyConstructor(ctor, args) {    return new ctor(...args);}

...but you won't need to, because the standard library function Reflect.construct() does exactly what you're looking for!