Есть у нас, предположим, функция и есть у нас массив произвольного количества аргументов для неё. Как нам её вызвать? Очень просто:
function f(a, b, c) { // ... } var args = [1, 2, 3]; f.apply(f, args); |
Здорово.
Следующая задача: у нас есть функция-конструктор и массив аргументов для неё. Как нам использовать этот массив совместно с оператором new
? Может new f.apply(f, args)
? Хрен там, здесь new
будет пытаться использовать в качестве конструктора результат от f.apply()
.
Нам нужно разбить задачу на две:
1. Создать пустой объект, но с нужной цепочкой прототипов.
2. Вызвать на нём конструктор для инициализации.
function applyForConstructor(Constr, args) { var instance, Fake; Fake = function () {}; Fake.prototype = Constr.prototype; instance = new Fake(); Constr.apply(instance, args); return instance; } var instance = applyForConstructor(f, [1, 2, 3]); |
Здесь нам пришлось создать фиктивный конструктор Fake
, чтобы создавать пустой объект, но с нужным наследованием.
Всё здорово, но JavaScript такой язык, который всегда позволяет извращаться и дальше, практически до бесконечности.
В ES5 мы можем уже не создавать фиктивный конструктор:
function applyForConstructor(Constr, args) { instance = Object.create(Constr.prototype); Constr.apply(instance, args); return instance; } |
Или свести конструктор через замыкание к функции без аргументов:
function createFuncWithoutArgs(f, args) { var newF = function () { return f.apply(this, args); }; newF.prototype = f.prototype; return newF; } var instance = new (createFuncWithoutArgs(f, args)); |
Или в том же ES5 использовать bind:
var instance = new (Function.prototype.bind.apply(f, [null].concat(args))); |
В общем, много забавных вещей придумать можно.
Месье знает толк в извращениях. :)
Алексей, 1.03.2013, 9:44
ты мутулз изобретаешь?
CTAPbIu_MABP, 5.03.2013, 4:05
>ты мутулз изобретаешь?
что конкретно из всего, что там наворочано?
vasa_c, 5.03.2013, 12:22
А для чего это? Я не шибко шарю в JS, но всё же, разве нельзя просто:
function f(a, b, c) {
// …
}
f(1, 2, 3);
f(1, 2);
f(1, 2, 3, 4);
f();
Denis, 13.09.2013, 12:40
Denis, можно. Но здесь не об этом.
vasa_c, 13.09.2013, 13:00