在做一些关于函数式编程的练习,并返回一个闭包时,遇到了这个例子,但无法弄清楚它是如何工作的:
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(arguments):
[object Arguments]
如何打印出结果,看[[3,2,1]]。 当我打印出“结果”时,我得到:
[object Object]
最佳答案
更正代码中的问题(缺少分号或太多)后,似乎在整个脚本执行过程中创建了一些闭包。
首先:
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 被调用者初始化后,它变成了一个变量,其中包含一个函数,该函数接受一个命名参数(称为目标),当被调用时,它将在任何情况下寻找一个名为 NAME(在本例中为“reverse”)的函数对象目标是。
当实际调用 rev 时,它还会返回一个函数,该函数在调用时将调用目标(传入的数组)上的目标方法(在本例中为反向)。但是 rev 在下一行运行之前没有被调用:
var result= _.map([[1,2,3]], rev);
这是这里发生的事情:_.map 的目的是获取一个项目列表并将一个函数应用于此列表中的每个项目。最终结果将是一个新数组,其中包含转换后的值。上面的行传递给 _.map 一个列表,其中只有一个项目;数组。它还向 _.map 传递一个函数来转换该列表中的每个项目;在这种情况下 rev.
所以 _.map 被调用,它在列表中的唯一项目上调用 rev,我们的 [1,2,3] 数组。函数 rev 具有返回另一个函数的效果,该函数在调用时会记住 NAME、target 和 args。此函数现在位于数组变量“result”的第一个元素内。
现在回答您的问题:
The output should be:
[[3,2,1]]
but i cannot prove it.
在测试代码中没有输出,只有一个名为 result 的最终变量。我认为你正在寻找的是最后的某个地方应该有一个反向数组。您可以在调用初始化结果后验证原始数组是否已被反转:
alert(result[0]().join());
Why is args:
0,1,2,3
args 在这里真的是一个转移话题; _.map 将 3 个参数传递给它的迭代器函数。当前值(在本例中为数组 [1,2,3],键或索引(在本例中为 0)和原始列表本身。当对参数调用 _.rest 时,它会切掉第一项,留下我们一个包含 0 和 [[1,2,3]] 的数组。当在此数组 (args) 上调用 reverse 时,它最终返回一个看起来像 [1,2,3,0] 的数组,这是这两个项目的反转. 我的测试从未显示 0,1,2,3。为什么 args 在这里是一个转移注意力的问题?因为当 reverse 被调用时 reverse 不接受任何参数,所以 args 被忽略。如果这是不同对象上的不同函数,你可能会因为调用 _.rest 而遇到问题。
Why is console.log(arguments):
[object Arguments]
因为您基本上是调用 toString() 来打印对象的类型。
How to print out the result, to see [[3,2,1]]. When I print out "result", I get:
[object Object]
您可以使用:
console.log(result[0]().join());
更新:这是带有工作代码的 jsbin 链接:http://jsbin.com/aYECIDo/5/edit?html,css,js,output
关于javascript - 这个javascript是如何工作的,函数式编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20363857/