部分应用 - 雄辩的Javascript

时间:2012-11-11 21:23:55

标签: javascript partial-application

我正在阅读Eloquent Javascript,我很难理解下面的例子。有人能够逐行解释吗?具体来说,我很困惑为什么第一个循环从一开始,以及为什么push方法被用于knownArgs和arguments。我知道这与“部分应用”有关,但是想要逐行更详细地解释究竟发生了什么。

var op = {
 "+": function(a,b){return a + b;}
};

function partial(func) {
 var knownArgs = arguments;

 return function() {
  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
   realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
   realArgs.push(arguments[i]);

  return func.apply(null, realArgs);
 };
}

map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);

2 个答案:

答案 0 :(得分:2)

knownArgs变量保留arguments值的副本,就像调用partial()时一样。该调用返回另一个函数,并且代码arguments内部是完全不同的列表 - 它们是传递给返回函数的参数。换句话说:

var p = partial(someFunction,“hello”,“world”);

调用p()时,knownArgs将是“hello”和“world”(well和someFunction,但请注意第一个循环从1开始)。如果对p()的调用如下:

p(“how”,“are”,“you”);

然后它首先将“hello”和“world”推送到realArgs列表(来自knownArgs),然后将这三个参数传递给p(),来自{{1} }。

编辑 - 评估arguments评估方式的逐步细分:

  1. 首先,必须评估map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);。我猜它会返回一个函数,可能是这样的:

    op["+"]
  2. 将“添加”功能和值function add(a, b) { return a + b; } 传递给1。因此在partial()partial()伪数组看起来像

    arguments

    也就是说,第一个参数是来自[ add, 1 ] 的“添加”功能,第二个参数是值op["+"]1在返回匿名函数之前唯一真正做的就是将partial()保存到arguments。必须这样做,因为奇怪的knownArgs伪变量总是在每个函数调用时分配一个新值。它被保存在这里,以便匿名函数中的代码可以在以后访问它。

  3. 现在,使用arguments返回的匿名函数和偶数数组,我们调用partial()。该功能可能看起来像这样(我没有这本书):

    map()

    function map(fn, list) { var i, result = []; for (i = 0; i < list.length; ++i) { result.push( fn( list[i] ) ); } return result; } 内,第一个参数是从之前调用map()返回的匿名函数。这个功能有什么作用?好吧,它结合了原始partial()调用的参数 - 除了第一个 - 与传递给它的参数。 partial()函数只传递一个参数,因此每次调用匿名函数时得到的参数列表将是传递给map()的值1,然后在每次迭代时,一个不同的参数列表中的数字。

  4. 一个更简单的例子是考虑你打电话时会发生什么:

    partial()

    也就是说,如果你调用partial(op["+"], 1)(2); 然后立即使用它的返回值(匿名函数)。效果与调用相同:

    partial()

答案 1 :(得分:1)

第一个循环从一个而不是零开始,因为knownArgs[0]包含函数,而不是它的参数。

push将单个元素追加到数组中。这是构建数组的一种相当常见的方法。

  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
    realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
    realArgs.push(arguments[i]);

将创建一个从knownArgsarguments连接的新数组。 knownArgs保存curried参数和函数(不附加到realArgs),arguments是函数调用时提供给函数的参数。