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

How does this javascript work, functional programming

本文关键字:函数 编程 工作 javascript 何工作 这个      更新时间:2024-03-14

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

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]

纠正代码中的问题(缺少分号或分号太多)后,在整个脚本执行过程中似乎会创建一些闭包。

第一:

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后,它就变成了一个变量,其中包含一个接受单个命名参数(称为target)的函数,当调用该参数时,它将在任何对象目标上寻找一个名为NAME(在本例中为"reverse")的函数。

当rev被实际调用时,它还返回一个函数,当被调用时,该函数将在target(传入的数组)上调用target方法(在这种情况下为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,0]的数组,这两个项被反转了。我的测试从未显示过0,1,2,3。为什么args在这里是在转移注意力?因为当reverse被调用时,reverse不接受任何参数,因此args被忽略。如果这是一个不同对象上的不同函数,您可能会因为调用_.rest.而遇到问题

为什么console.log(参数):

[对象参数]

因为您基本上是在调用toString(),它将打印对象的类型。

如何打印出结果,请参阅[[3,2,1]]。当我打印出来"结果",我得到:

[对象对象]

您可以使用:

console.log(result[0]().join());

UPDATE:这是带有工作代码的jsbin链接:http://jsbin.com/aYECIDo/5/edit?html,css,js,输出

使用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采用作用域的第一个参数和一组参数来调用函数。