这个javascript如何工作,函数式编程

时间:2013-12-03 23:29:57

标签: javascript closures

在进行一些关于函数式编程的练习并返回一个闭包时,遇到了这个例子,并且无法弄清楚它是如何工作的:

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]

2 个答案:

答案 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:

     

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时不接受任何参数,因此args被忽略。如果这是另一个对象的不同函数你因为调用_.rest而可能会遇到问题。

  

为什么是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