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]))();
Ответы
Ответ 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]);