JavaScript中的立即调用函数表达式(IIFE)函数是一种构造,允许您在定义函数后立即调用它。
在本文中,我们将理解,尽管它具有以前的优点,但为什么值得放弃使用IIFE。我们可以在自治块中声明变量
自从ES6标准诞生以来,我们就可以使用let和const在一个块内声明变量和常量。与该标准一起,还可以将变量和常量分配到外部无法访问的自治块中。例如:{
let x = 1;
}
这样,x将无法从外部访问。这显然优于:(()=>{
let x = 1;
})();
现在几乎所有现代浏览器都支持ES6,我们必须停止使用IIFE来将变量与外界分开。隔离变量的另一种方法是使用模块,这些模块现在也没有问题。在我们导出它们之前,它们将无法用于其他模块。我们可以摆脱几乎所有的封闭
闭合是一种机制,通过该机制,函数可以记住其外部变量并可以访问它们。如果在函数内部创建另一个函数并将其返回,则返回的函数将能够访问外部函数内部的外部变量。例如,在这里我们可以得到一些副作用:const id = (() => {
let count = 0;
return () => {
++count;
return `id_${count}`;
};
})();
再说一次,现在围起来整个花园毫无意义,因为我们有用于数据隔离的自治模块和模块。我们只需将所有这些放到我们自己的模块中,就不必担心数据访问。封闭会产生副作用,效果不是很好,因为最佳实践和常识指示我们尽可能避免使用它们。在这种情况下,它们使测试不干净的功能变得困难。此外,在可以避免这种情况的情况下,您不应该产生嵌套函数:有了它们,与没有它们相比,代码变得更加混乱。最好的替代方法是将它们替换为模块:let count = 0;
export const id = () => {
++this.count;
return `id_${count}`
}
在上面的代码中,我们对count变量使用了相同的声明,并导出了id()函数,以便其他模块可以使用它。因此,我们仅在不使用IIFE的情况下隐藏count并打开id()。结果,我们减少了嵌套,并且无需定义另一个函数并运行它。我们可以为变量创建别名。
我们可以这样写:window.$ = function foo() {
};(function($) {
})(jQuery);
但是现在无需使用IIFE创建别名。使用模块,我们可以简单地以其他名称导入变量,从而为其创建别名。然后写:import { $ as jQuery } from "jquery";
const $ = () => {};
此外,不应将新属性添加到window对象,因为这会污染全局范围。我们可以轻松获得全局对象。
随着globalThis的到来,我们不必担心全局对象在各种环境中的名称成为标准。我们可以使用IIFE捕获全局对象:(function(global) {
})(this);
但是现在这不是必需的。是的,在没有此可能之前,只需编写以下行:const globalObj = self || window || global;
更准确地说,您可以这样编写:const getGlobal = () => {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
然后,您无法添加使用IIFE时出现的其他函数调用和嵌套。我们可以使缩小变得更容易
使用JavaScript模块,我们不再需要将其余代码与IIFE分开以适当地缩小文件大小。Webpack,Browserify,Parcel,汇总等可以正确使用模块,因此我们必须使用它们来创建更简洁的代码。结论
现在该停止在我们的代码中使用IIFE了。这增加了额外的功能和冗余嵌套。另外,现在这已经过时了:IIFE甚至在JavaScript模块出现和广泛使用之前就已使用。在2020年,我们必须使用模块和自治块来分隔代码。为了防止外部访问模块内部的变量,我们可以使用块作用域。