How to pass arguments dynamically to a new call?

3

If I have a JavaScript function and I want to call it by passing a list of arguments, I use apply :

var x = f(1,2,3);
var x = f.apply(null, [1,2,3]);

For the first time, I came across a case where I need to call a constructor with a list of arguments, and the first thing I tried (even though I suspected it was going to go wrong) was simply same:

var x = new f(1,2,3);
var x = new f.apply(null, [1,2,3]);

And it did not really work ... Is there any way to do this? I have to create several objects in a loop, and I was forced to do so:

var x = new f(lista[0], lista[1], lista[2]);

That's not so bad in the case of a constructor with only 3 parameters, but I wonder if there is a more concise or "smart" way.

    
asked by anonymous 15.09.2015 / 08:10

1 answer

3

In SOen there is an interesting answer with this solution:

function construtor(Construtor) {
    return new (Construtor.bind.apply(Construtor, arguments));
}

Basically a function that:

  • change indicator / scope of this to Class / Builder passed to you
  • applies the arguments passed to it (not indicated in the function declaration because they are optional)
  • returns new of this constructor.

An example would be:

var Pessoa = function (nome) {
    this.nome = nome || 'Anónimo';
    this.getNome = function () {
        return this.nome;
    }
}

var Ana = new Pessoa('Ana');
console.log(Ana.getNome()); // "Ana"

function construtor(Construtor) {
    return new (Construtor.bind.apply(Construtor, arguments));
}

var Pedro = construtor(Pessoa, 'Pedro');
console.log(Pedro.getNome()); // "Pedro"

var Maria = construtor(Pessoa, 'Maria');
console.log(Maria.getNome()); // "Maria"

jsFiddle: link

Note:

When we use construtor internally it does Classe.bind.apply(Classe, argumentos) , which means that .bind will be called with context Classe and with arguments of argumentos variable. Since .bind consumes the first argument as the context of the function that is binded, this first element of array argumentos is discarded since new creates a new context.

Another way, without having disposable elements in arguments might look like this:

function construct(constructor, args) {
    function F() {
        return constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    return new F();
}
    
15.09.2015 / 10:31