2008-12-16 10 views
85

Можно создать дубликат:
How can I pre-set arguments in JavaScript function call? (Partial Function Application)Как передать ссылку на функцию с параметрами?

Мне нужно иметь возможность передать ссылку на функцию с заданным набором параметров.

Вот пример передачи ссылки без параметров:

var f = function() { 
    //Some logic here... 
}; 

var fr = f; //Here I am passing a reference to function 'f', without parameters 
fr(); //the 'f' function is invoked, without parameters 

Теперь то, что мне нужно сделать, это пройти тот же f функцию, но на этот раз я должен был бы передать параметры Справка. Теперь, я могу сделать это с анонимной функции и вызвать f функции с параметрами внутри вновь созданной функции, как, например:

var f = function() { 
     //Some logic here... 
    }; 

var fr = function (pars) { 
    f(pars); 
}; //Here I am creating an anonymous function, and invoking f inside it 

fr({p : 'a parameter'}); //Invoking the fr function, that will later invoke the f function with parameters 

Но мой вопрос, Есть ли способ передать прямую ссылку на f Функция С параметрами до fr, но без включения ее в анонимную функцию?

Что мне нужно сделать, чтобы назначить fr, чтобы сделать его invokable без параметров (fr()), так что F (1,2,3) выполняется, когда fr вызывается?

[UPDATE] Я последовал Jason Bunting «s ответ на here о частичной функции и функции JavaScript он размещает там именно то, что я искал. Вот решение:

function partial(func /*, 0..n args */) { 
    var args = Array.prototype.slice.call(arguments).splice(1); 
    return function() { 
    var allArguments = args.concat(Array.prototype.slice.call(arguments)); 
    return func.apply(this, allArguments); 
    }; 
} 
+0

По какой-то причине, у меня были проблемы с первым утверждением (вар арг = Array.prototype.slice.call (аргументы) .splice (1);) и ему пришлось использовать это вместо: var args = new Array(); для (var i = 1; i

+0

на всякий случай кому-то нужно это: 'Function.prototype.pass = function() { var args = arguments, func = this; return function() {func.apply (this, args);} }; ' –

ответ

77

То, что вы после того, как называется частичное применение функции.

Не обманывайтесь теми, кто не понимает тонкой разницы между этим и каррированием, они являются разных.

Приложение с частичной функцией может использоваться для реализации, но не является currying. Вот цитата из a blog post on the difference:

Где частичное применение берет функцию и из нее строит функцию, которая принимает меньше аргументов, выделка строит функцию, которые принимают несколько аргументов по составу функций, которые каждый берут один аргумент.

Это уже ответил на этот вопрос см для ответа: How can I pre-set arguments in JavaScript function call?

Пример:

var fr = partial(f, 1, 2, 3); 

// now, when you invoke fr() it will invoke f(1,2,3) 
fr(); 

Опять же, видим, что вопрос о деталях.

+0

Что мне нужно назначить' fr', чтобы сделать его invokable без параметров ('fr()'), так что f (1 , 2,3) выполняется, когда вызывается 'fr' –

+4

Примечание для будущих читателей, убедитесь, что вы включили функцию« частичного », предоставленную Джейсоном в [его другом ответе] (http://stackoverflow.com/a/321527/ 1366033) – KyleMit

+2

В качестве альтернативы «частичной» функции Джейсона библиотека [UnderscoreJS] (http://underscorejs.org) также предлагает функцию '_.partial'. – sfletche

-4

Следующие эквивалентен ваш второй кодовый блок:

var f = function() { 
     //Some logic here... 
    }; 

var fr = f; 

fr(pars); 

Если вы действительно хотите передать ссылку на функцию в какую-то другую функцию, вы можете сделать что-то вроде этого:

function fiz(x, y, z) { 
    return x + y + z; 
} 

// elsewhere... 

function foo(fn, p, q, r) { 
    return function() { 
     return fn(p, q, r); 
    } 
} 

// finally... 

f = foo(fiz, 1, 2, 3); 
f(); // returns 6 

Вы почти наверняка лучше используете фреймворк для такого рода вещей.

2

Вы также можете перегрузить прототип функции:

// partially applies the specified arguments to a function, returning a new function 
Function.prototype.curry = function() { 
    var func = this; 
    var slice = Array.prototype.slice; 
    var appliedArgs = slice.call(arguments, 0); 

    return function() { 
     var leftoverArgs = slice.call(arguments, 0); 
     return func.apply(this, appliedArgs.concat(leftoverArgs)); 
    }; 
}; 

// can do other fancy things: 

// flips the first two arguments of a function 
Function.prototype.flip = function() { 
    var func = this; 
    return function() { 
     var first = arguments[0]; 
     var second = arguments[1]; 
     var rest = Array.prototype.slice.call(arguments, 2); 
     var newArgs = [second, first].concat(rest); 

     return func.apply(this, newArgs); 
    }; 
}; 

/* 
e.g. 

var foo = function(a, b, c, d) { console.log(a, b, c, d); } 
var iAmA = foo.curry("I", "am", "a"); 
iAmA("Donkey"); 
-> I am a Donkey 

var bah = foo.flip(); 
bah(1, 2, 3, 4); 
-> 2 1 3 4 
*/ 

 Смежные вопросы

  • Нет связанных вопросов^_^