【问题标题】:Explain the anonymous function code example in Eloquent Javascript Chapter 6讲解 Eloquent Javascript 第 6 章中的匿名函数代码示例
【发布时间】:2012-09-01 12:57:32
【问题描述】:

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

根据我对这段代码的理解:

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);

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

【问题讨论】:

    标签: javascript anonymous-function


    【解决方案1】:

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

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

    或者

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

    它们被称为 IIFE。 (以上引用)

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

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

    【讨论】:

    • 或者如果你觉得勇敢,你可以这样做new function() { }
    • 应该指出,问题中显示的number 参数将需要删除,因为它会影响number 变量,或者number 需要作为参数传递到 IIFE。
    【解决方案2】:

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

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

    function (number) {
        total += number;
    }
    

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

    据我了解,无法调用语法function (number) {},但这不是第一个示例指示函数执行的操作吗?

    并非如此。在第一个示例中,您有一个 函数表达式,因为该函数是在表达式上下文中定义的(它作为参数传递给另一个函数)。函数表达式不需要名称。表达式被评估为一个函数对象,然后作为参数传递给forEachfunction (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);
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 第二个例子没有声明函数。这是无效的语法,alert 永远不会发生。
      • 好吧,至少它在 rhino 中运行,将 alert 替换为 print,并在代码之前的某处声明 total 并带有初始值(print 确实会输出此初始值)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      相关资源
      最近更新 更多