Подтвердить что ты не робот

Javascript - создать экземпляр с массивом аргументов

Я знаю возможность вызова функции с массивом аргументов с применением (obj, args); Есть ли способ использовать эту функцию при создании нового экземпляра функции?

Я имею в виду что-то вроде этого:

function A(arg1,arg2){
    var a = arg1;
    var b = arg2;
}

var a = new A.apply([1,2]); //create new instance using an array of arguments

Надеюсь, вы понимаете, что я имею в виду... ^^^

Спасибо за вашу помощь!

Решено!

Я получил правильный ответ. Чтобы ответить на мой вопрос:

function A(arg1,arg2) {
    var a = arg1;
    var b = arg2;
}

var a = new (A.bind.apply(A,[A,1,2]))();
4b9b3361

Ответ 1

var wrapper = function(f, args) {
    return function() {
        f.apply(this, args);
    };
};

function Constructor() {
    this.foo = 4;
}
var o = new (wrapper(Constructor, [1,2]));
alert(o.foo);

Мы берем функцию и аргументы и создаем функцию, которая применяет аргументы к этой функции с этой областью.

Затем, если вы вызываете его с помощью нового ключевого слова, он переходит в новый новый this и возвращает его.

Важное значение имеют скобки

new (wrapper(Constructor, [1,2]))

Вызывает новое ключевое слово для функции, возвращенной из оболочки, где

new wrapper(Constructor, [1,2])

Вызывает новое ключевое слово в функции-обёртке.

Причина, по которой она должна быть обернута, заключается в том, что this, к которой вы применили ее, устанавливается с новым ключевым словом. Новый объект this должен быть создан и передан в функцию, что означает, что вы должны вызвать .apply(this, array) внутри функции.

Live пример

В качестве альтернативы вы можете использовать метод ES5 .bind

var wrapper = function(f, args) {
    var params = [f].concat(args);
    return f.bind.apply(f, params);
};

См. пример

Ответ 2

с ECMAscript 5 вы можете:

function createInstanceWithArguments (fConstructor, aArgs) {
    var foo = Object.create(fConstructor.prototype);
    fConstructor.apply(foo, aArgs);
    return foo;
}

Ответ 3

Ответ на

@Raynos хорошо работает, за исключением того, что в версии, отличной от ES5, отсутствует экземпляр конструктора после создания экземпляра.

Здесь мой обновленный метод cApply:

var cApply = function(c) {
  var ctor = function(args) {
    c.apply(this, args);
  };
  ctor.prototype = c.prototype;
  return ctor;
};

Что можно использовать следующим образом:

var WrappedConstructor = cApply(Constructor);
var obj = new WrappedConstructor([1,2,3]);

// or inline like this.    
var obj2 = new (cApply(Constructor))([1,2,3]);

JSFiddle для справки.

Ответ 4

Вы можете выполнять следующие функции:

function A(arg1, arg2) {
    // ...
}

function A12() {
    A(1, 2);
}

Вы даже можете построить карри factory:

function A_curry() {
    var args = arguments;
    return function () {
        A.apply(null, args);
    };
}

Ответ 5

Вы можете использовать Object.create() для создания нового экземпляра и вызвать конструктор в экземпляре после этого:

var args = [1,2,3];
var instance = Object.create(MyClass.prototype);
MyClass.apply(instance, args);

или в одной строке:

var instance = MyClass.apply(Object.create(MyClass.prototype), args);

но не забывайте return this; в MyClass этим однострочным решением.

Если у вас нет Object.create(), то очень просто написать один:

Object.create = function (source){
    var Surrogate = function (){};
    Surrogate.prototype = source;
    return new Surrogate();
};

Вы можете дополнительно записать функцию Function.newInstance() или Function.prototype.newInstance():

Function.newInstance = function (fn, args){
    var instance = Object.create(fn.prototype);
    fn.apply(instance, args);
    return instance;
};

so var instance = Function.newInstance(MyClass, args);.

Примечание. Не рекомендуется переопределять классы.

Ответ 6

Что делать, если у вас есть имя объекта объекта, хранящегося в переменной с именем className?

var className = 'A'

В соответствии с этот ответ здесь все становится очень простым и простым, используя метод ECMAScipt5 Function.prototype.bind.

С массивом аргументов:

new ( Function.prototype.bind.apply( className, arguments ) );

Или с помощью списка аргументов:

new ( Function.prototype.bind.call( className, argument1, argument2, ... ) );

Одна строка, нет необходимости в обертке.

Ответ 7

У меня была одна и та же проблема, а также я хотел сохранить свойства прототипа целевого объекта. Посмотрев на ответы, просто придумал довольно простое решение. Думал, что я мог бы также поделиться им для любого будущего ищущего:)

// Define a pseudo object that takes your arguments as an array
var PseudoObject = function (args) {
    OtherObject.apply(this, args);
};
// if you want to inherit prototype as well
PseudoObject.prototype = new OtherObject();

// Now just use the PseudoObject to instantiate a object of the the OtherObject
var newObj = new PseudoObject([1, 2, 3]);