结合返回嵌套函数的JavaScript函数声明或表达式



这段代码出现在一个非常流行的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. 我试图弄清楚他们从函数返回函数的原因(不幸的是,这里没有提供解释(。如果用参数声明外部函数,执行计算,然后简单地返回值,则会更简单明了。为什么有必要(在这种情况下;似乎可以在这里找到对一般情况的答案(以这种方式表达函数?

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

使用像示例中那样立即调用的匿名函数通常只是为了隔离代码的范围。特别是在这种情况下,"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);
};

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

在数字2的部分答案中,命名函数将在堆栈跟踪中报告其名称,而分配给变量或常量的匿名函数则不会。因此,这有点倾向于只声明函数。

然而,你可以命名一个函数,并将其分配给一个变量或常数,而不会出现这样的问题:

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

如果你喜欢指定的功能,这会让你两全其美。

是您的第一个问题:当函数用于封装模块和模拟命名空间(或封装(范围时,上面使用的构造是有意义的。所有top函数的本地变量都将自动以"package"为作用域。在上面的例子中,它没有被使用,所以我也认为它被过度设计了

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

1-这就是所谓的IIFE。立即调用的函数表达式。它有几个先锋:首先,它是一种创建类似OOP的功能的方法,比如私有和公共函数,然后它是一个封装东西的方法,这样它们就不会污染全局命名空间。如果你声明了一个全局函数,而你使用的某个库使用了相同的函数名,会发生什么?最后一个赢了,这就造成了很难找到的bug。这也是创建模块的一种方式(请在此处阅读有关模块的更多信息(。

2-取决于代码作者使用的逻辑和事物的组织方式。使用vars而不是函数往往更简洁。数组函数出现后,这种情况变得越来越普遍。但这仍然是你的选择。

最新更新