在进行一些关于函数式编程的练习并返回一个闭包时,遇到了这个例子,并且无法弄清楚它是如何工作的:
function invoker (NAME, METHOD) {
return function(target) {
var targetMethod = target[NAME];
var args = _.rest(arguments);
return function() { return targetMethod.apply(target, args);});
};
};
测试:
var rev = invoker('reverse', Array.prototype.reverse);
var result= _.map([[1,2,3]], rev);
输出应为:
[[3,2,1]]
但我无法证明这一点。
具体问题: 为什么是args:
0,1,2,3
为什么是console.log(参数):
[object Arguments]
如何打印出结果,看[[3,2,1]]。 当我打印出“结果”时,我得到:
[object Object]
答案 0 :(得分:1)
使用console.log和带有实际开发工具的现代浏览器..如chrome或firefox + firebug。然后你应该能够在控制台中看到结果。或者,当您在HTML中打印出来时,使用JSON.stringify对其进行序列化。示例:document.write(JSON.stringify(result))
。
那应该写出你所看到的JSON表示。
关于[1,2,3]查看MDN中的.apply函数。
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
Apply接受范围的第一个参数,以及一个参数数组,以便使用。
调用该函数答案 1 :(得分:1)
在纠正代码中的问题(缺少分号或太多)后,似乎会在整个脚本的执行过程中创建一些闭包。
首先:
function invoker (NAME, METHOD) {
return function(target) { // In the example this is rev
// Begin Scope1 (closure)
var targetMethod = target[NAME]; // NAME is trapped here in Scope1 (defined outside of this function) when the function is executed!
var args = _.rest(arguments);
return function() { //
// Begin Scope2 (closure)
return targetMethod.apply(target, args); // target and args are trapped here in Scope2 (defined in Scope1's function) when the function is executed!
};
};
}
调用者在调用它之前什么都不做,并且在调用实际调用之前,第一个闭包(Scope1就是)不会被创建:
var rev = invoker('reverse', Array.prototype.reverse);
在rev由invoker初始化之后,它已成为一个变量,它包含一个接受单个命名参数(称为目标)的函数,当被调用时,它将查找一个名为NAME的函数(在本例中为'reverse')对象目标是。
当实际调用rev时,它还返回一个函数,当调用它时,将调用目标上的目标方法(在这种情况下为反向)(传入的数组)。但是直到下一行运行才开始调用rev:
var result= _.map([[1,2,3]], rev);
以下是这里发生的事情:_. map的目的是获取项目列表并将函数应用于此列表中的每个项目。最终结果将是一个包含转换值的新数组。上面的行传递给_.map一个列表,其中只包含一个项目;数组。它还传递_.map函数来转换该列表中的每个项目;在这种情况下转。
因此调用了_.map并且它在列表中的唯一项目(我们的[1,2,3]数组)上调用了rev。函数rev具有返回另一个函数的效果,当被调用时,它将记住NAME,target和args。此函数现在位于数组变量'result'的第一个元素内。
现在提出您的问题:
输出应为:
[[3,2,1]]
但我无法证明这一点。
在测试代码中没有输出,只有一个名为result的最终变量。我认为你在寻找的是到底应该有一个反向阵列。在调用初始化结果后,您可以使用以下内容验证原始数组是否已反转:
alert(result[0]().join());
args在这里真的是一个红鲱鱼; _.map将3个参数传递给它的迭代器函数。当前值(在本例中为数组[1,2,3],键或索引(在本例中为0)和原始列表本身。当在参数上调用_.rest时,它会切掉第一个项目而离开我们一个包含0和[[1,2,3]]的数组。当在这个数组(args)上调用reverse时,它最终返回一个看起来像[1,2,3,0]的数组,这两个项目是相反的我的测试从未显示过0,1,2,3。为什么args在这里是红色鲱鱼?因为当反向调用reverse时不接受任何参数,因此args被忽略。如果这是另一个对象的不同函数你因为调用_.rest而可能会遇到问题。为什么是args:
0,1,2,3
为什么是console.log(参数):
[object Arguments]
因为你基本上是调用toString()来打印对象的类型。
如何打印出结果,看[[3,2,1]]。当我打印出来 “结果”,我明白了:
[object Object]
您可以使用:
console.log(result[0]().join());
更新:这是带有工作代码的jsbin链接:http://jsbin.com/aYECIDo/5/edit?html,css,js,output