3

我正在阅读 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]);
4

2 回答 2

2

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

var p = partial(someFunction, "hello", "world");

p()被调用时,knownArgs将是“hello”和“world”(当然,someFunction但请注意第一个循环从 1 开始)。如果调用p()看起来像这样:

p(“如何”、“是”、“你”);

然后它将首先将“hello”和“world”推送到realArgs列表中(from knownArgs),然后将三个参数传递给p(),from arguments

编辑map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);- 如何评估的逐步细分:

  1. 首先,op["+"]必须进行评估。我猜它会返回一个函数,可能是这样的:

    function add(a, b) {
      return a + b;
    }
    
  2. 该“添加”函数和值1被传递给partial(). 因此伪数组内部看起来partial()arguments

    [ add, 1 ]
    

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

  3. 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传递给的值partial(),然后在每次迭代中,列表中的一个不同的偶数。

一个更简单的例子是考虑调用时会发生什么:

partial(op["+"], 1)(2);

也就是说,如果你调用partial()然后立即使用它的返回值(匿名函数)。效果将与调用相同:

add(1, 2);
于 2012-11-11T21:44:08.147 回答
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]);

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

于 2012-11-11T21:43:58.367 回答