JavaScript函数声明或表达式,并返回嵌套函数

时间:2018-12-18 20:53:28

标签: javascript function ecmascript-6 declaration

此代码出现在一个非常流行的JS教程中:

const sum = (function() {
  "use strict";
  return function sum(...args) {
    return args.reduce((a, b) => a + b, 0);
  };
})();
console.log(sum(1, 2, 3)); // 6
  1. 我试图弄清它们从函数返回函数的原因(不幸的是,此处未提供解释)。如果使用参数声明外部函数,执行计算,然后简单地返回值,则将更加简单明了。为什么要用这种方式表达一个功能(在这种情况下;似乎可以找到对一般情况的答案here)?

  2. 是否有理由表达一个函数而不是声明它?即将函数表示为varletconst而不是简单地使用function关键字来声明它?每种方式的优点是什么?我读过here,说除了吊装,这完全是一个风格上的决定。那么,总是声明函数而不是表达它们会更安全吗?我一定在这里缺少一些基本知识。

4 个答案:

答案 0 :(得分:1)

使用一个像您的示例中那样立即被调用的匿名函数通常是出于隔离代码范围的唯一目的。特别是在这种情况下,"use strict"的使用将严格模式仅限制为顶级函数中的代码。

如您所说,您可以只具有一个函数,而不是两个,但是结果不一样:

const sum = (function() {
  "use strict";
  var x = something(); // strict mode enforced here
  return function sum(...args) {
    return args.reduce((a, b) => a + b, 0);
  };
})();

在这里:

var x = something(); // strict mode not enforced here
function sum() {
    "use strict";
    return arguments.reduce((a, b) => a + b, 0);
};

另外,虽然在第二种方法中必须在全局范围内声明函数,但在第一种方法中,可以在顶级函数中声明许多函数而不会污染全局范围。

答案 1 :(得分:0)

对于数字2的部分回答,一个命名函数将在堆栈跟踪中报告其名称,而分配给变量或常量的匿名函数则不会。因此,这稍微偏向于只声明函数。

但是,您可以命名一个函数并将其分配给变量或常量,而不会出现以下问题:

let sum = function sum(...args) {
  return args.reduce((a, b) => a + b, 0)
}

如果您更喜欢分配的功能,则可以为您带来两全其美的体验。

答案 2 :(得分:0)

是您的第一个问题:当使用函数来打包模块并模拟名称空间(或包)作用域时,上面使用的构造才有意义。所有功能最强大的本地var都将自动成为“包”范围。在上面的示例中,没有使用它,所以我也认为它是过度设计的

第二个问题-匿名fn,var和let具有明显不同的可见性。这通常在设计中很重要,可以帮助您更好地控制需要暴露的内容。这是我唯一能想到的原因。

答案 3 :(得分:0)

1-这就是所谓的IIFE。立即调用的函数表达式。它具有几个优点:首先,它是一种创建类似于OOP的功能(例如私有和公共功能)的方法,然后是一种封装事物以免它们污染全局名称空间的方法。如果声明全局函数,并且使用的某些库使用相同的函数名,该怎么办?最后一个获胜,这会导致难以发现错误。这也是一种创建模块的方法(有关模块here的更多信息)。

2-取决于代码作者使用的逻辑和事物的组织方式。使用vars代替function往往更简洁。在数组函数问世之后,这变得越来越普遍。但这仍然是您的选择。