我对这个概念的理解是,可以用iifes模拟一个“私有”作用域,以防止全局作用域变得混乱。
现在,ECMAScript 6已经实现了相当广泛的实现,并且使我们能够通过const和let来访问块级作用域,还有其他理由使用iife模式吗? (除了提供向后兼容性之外。)
答案 0 :(得分:3)
普通块无法实现的IIFE的好处之一就是可以将其输出分配给const
。例如:
const output = (() => {
// some calculations that take a few lines
const now = new Date();
return now.getMinutes() + ':' + now.getSeconds();
})();
console.log(output);
假设我们想将now
变量包含在IIFE中,因为它仅与计算output
有关,而在其他任何地方都不需要。如果为此目的而使用普通块,则只有用output
而不是let
声明const
才有可能:
let output;
{
// some calculations that take a few lines
const now = new Date();
output = now.getMinutes() + ':' + now.getSeconds();
}
console.log(output);
由于const
大大提高了代码的可读性(在我看来),这可以说是一个可能的原因,尽管代码样式有所不同,但还是比普通代码块更喜欢IIFE。
也就是说,如果要extract till you drop,有人可能会说要避免IIFE,并声明一个独立的函数,然后可以将其导入并调用:
function getTimeStr() {
const now = new Date();
return now.getMinutes() + ':' + now.getSeconds();
}
// another file:
// import getTimeStr from './getTimeStr';
const output = getTimeStr();
console.log(output);
与上面的代码段一样,使用现代代码打包器(例如Webpack)(或ES6模块)可能会比使用纯块的ES6对更少的IIFE使用产生更大的影响。它取决于一个人喜欢的编码样式,但是使用IIFE无疑是一个可能选择的选择。
答案 1 :(得分:1)
在我的代码中使用IIFE的所有常见原因几乎都已被块范围的变量取代。
我在实际代码中看到的一种用途是模拟顶级await
:
(async function() {
try {
const data1 = await something1();
const data2 = await something2(data1);
...
} catch(e) {
...
}
})();
我看到IIFE的其余原因是,当您希望利用诸如return
或throw
之类的功能来停止执行剩余代码的定义部分时(不嵌套在if
)或要递归调用的内容。但是,当然,您也可以使用本地范围内的命名函数来获得所有这些优点。
但是,如果函数中的代码从访问父范围变量中受益匪浅,则它确实希望是内联的,这为IIFE结合了将单独函数的优点与对父类的内联访问的优点结合在一起提供了可能的原因范围。
现在,实际上,大多数/所有这些情况都可以通过一些重构来解决,要么在本地范围内定义命名函数(这样它仍然可以访问父范围的变量),或者仅从父范围传递东西作用域到一个命名函数,以便它能够以这种方式访问它们,实际上,这就是我们所有人在其他语言中所做的事情。唯一的花费就是再增加一个本地函数名称(如果要隐藏它,甚至可以在本地作用域)。