2012-11-11 40 views
3

我正在阅读雄辩的Javascript和我有困难的时候了解下面的例子。任何人都可以做一个逐行的解释?具体来说,我很困惑,为什么第一个循环从一开始,以及为什么push方法在knownArgs和arguments上都被使用。我知道这与“部分应用”有关,但希望更详细地解释逐行发生的事情。部分应用程序 - 雄辩的Javascript

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

我花了_literally_ 2秒找到这个http://www.drdobbs.com/open-source/currying-and-partial-functions-in-javasc/ 231001821。阅读所有关于它的内容。 – elclanrs

+0

谢谢,我会阅读。有希望的我仍然可以得到上述的解释。 – KMcA

+0

我用更多的解释更新了我的答案。碰巧,我只是在几个星期前教了几个JavaScript类,其中有些例子与此非常相似:-) – Pointy

回答

2

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

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

当调用p()时,knownArgs将会是“你好”和“世界”(也是someFunction,但请注意第一个循环从1开始)。如果拨打p()看起来像这样:

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

那么它会先推“你好”和“世界”到realArgs列表(从knownArgs),然后传递到p()三个参数,从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 ] 
    

    也就是说,第一个参数是从op["+"]“添加”功能,第二个是该值1partial()在返回匿名函数之前唯一真正做的是将arguments保存为knownArgs。必须这样做,因为奇怪的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); 
+0

谢谢。我理解你的答案,它与上面的代码有关系。我对部分应用的概念似乎还很模糊。除了elclanrs发布的链接之外,你是否对任何完全陌生的编程人员的解释有任何建议? – KMcA

+0

@KMcA对于新编程的人来说,这是一些相当奇特的东西:-)尽管这并不难;这只是一套你必须与之合作的想法,才能熟悉它。从JavaScript开始是一个好主意,因为这是一个用这种概念玩相对友好的环境。关键是,在JavaScript和其他一些语言中,函数不仅仅是代码块,还包括对象,并且可以像对待任何其他对象一样处理。它们只是具有可作为函数调用的附加功能! – Pointy

+0

我一直在考虑将此作为本书的一个停止点,因为它似乎在学习一些高级概念,但我知道在哪里接近实际使用这些概念的地方。当你说“花哨的东西”时,你会说我可能会更好地支持并做一些编程书籍/在线课程的介绍吗?例如,我坐在桌子上的“学习计划”,但是讨厌停止雄辩的Javascript而没有完成。 – KMcA

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是函数在调用时提供的参数。