3

我在调用Eloquent Javascript(第 6 章)中的匿名函数代码示例的 sum 函数时遇到了困难,虽然我理解这篇文章中澄清的内容,但我真的不明白匿名函数是如何被调用的。

据我了解这段代码:

function forEach(array, action) {
  for (var i = 0; i < array.length; i++)
    action(array[i]);
}

function sum(numbers) {
  var total = 0;
  forEach(numbers, function (number) {
    total += number;
  });
  return total;
}
alert(sum([1, 10, 100, 1000]));

类似于此代码(感谢@CKKiller 在另一个线程中的帮助):

numbers = [1, 10, 100, 1000];
for (var i = 0; i < numbers.length; i++) {
  var number = numbers[i];

  function (number) {
    total += number;
  }
}
alert(total);

但是我无法运行第二个代码示例,它有什么问题?据我了解,无法调用语法函数 (number) {},但这不是第一个示例指示函数执行的操作吗?

4

3 回答 3

3

在第二个代码片段中,您只是声明了一个匿名函数。调用它,它应该可以正常工作。要“立即调用函数表达式”,您应该这样做:

(function (){
    // Your code
})();

或者

(function (){
    // Your code
}());

他们被称为IIFE。(在上面的引用中)

正如 user1600680 在下面的评论中指出的那样,要编辑您的代码,您必须number从参数列表中删除。它会是这样的:

(function () {
  total += number;
})();
于 2012-09-01T13:00:24.707 回答
2

但是我无法运行第二个代码示例,它有什么问题?

您有一个没有名称的函数声明

function (number) {
    total += number;
}

函数声明总是必须包含函数的名称。请参阅规范中的第 13 节

根据我的理解,不可能调用 syntax function (number) {},但这不是第一个示例指示函数执行的操作吗?

不是它不是。在第一个示例中,您有一个函数表达式,因为该函数是在表达式上下文中定义的(它作为参数传递给另一个函数)。函数表达式不需要名称。表达式被评估为一个函数对象,然后作为参数传递给forEach. function (number) {}不调用函数,它定义它。

我真的不明白匿名函数是怎么调用的

它没有什么特别之处。重要的方面是函数是第一类对象,即它们可以像任何其他值(原始值或对象)一样被分配给变量并传递给其他函数。 action指的是一个函数,因此您可以使用 . 调用该函数action()。该函数直接传递给forEach

forEach(numbers, function (number) {
    // ...
});

虽然它是在内部调用forEach的,但它可以更新 的值,total因为它是在其中定义sum,因此是一个可以访问内部所有局部变量的闭包sum

您也可以事先定义函数:

function sum(numbers) {
    var total = 0;
    function add(number) {
       total += number;
    }
    forEach(numbers, add);
    return total;
}

但是,如果您只使用一次值,则无需先将其分配给变量(或为此声明一个函数)。例如,您还将数组直接传递给sum

sum([1, 10, 100, 1000])

而不是首先将其分配给变量:

var numbers = [1, 10, 100, 1000];
sum(numbers);

与显示类似行为的第一个代码等效的是:

var numbers = [1, 10, 100, 1000],
    total = 0,
    action = function(number) { // variable assignment -> expression context
        total += number;
    };

for (var i = 0; i < numbers.length; i++) {
  var number = numbers[i];
  action(number);
}

alert(total);
于 2012-09-01T13:19:57.453 回答
1

第二个例子不调用匿名函数,它只声明函数。total因此,for 循环对变量没有任何作用(我假设它之前在某处声明过)。alert(total)只会输出最后分配给 total 的内容(因为匿名函数永远不会被调用,不会total被更新)。

于 2012-09-01T13:05:35.563 回答