为什么现在该停止使用JavaScript IIFE

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年,我们必须使用模块和自治块来分隔代码。

为了防止外部访问模块内部的变量,我们可以使用块作用域。


All Articles