JavaScript IIFE 设计模式






3.74/5 (17投票s)
JavaScript 中的立即调用函数表达式
IIFE (立即调用函数表达式)
本文简要介绍了 JavaScript 中的单例模式。
本文还提供了更多关于面向对象 JavaScript 设计的主题。
IIFE (立即调用函数表达式) 是 JavaScript 中的一个重要概念。它是一种常用的设计模式,用于封装一组无法在外部访问的变量和函数。
这些是匿名函数,它们被包裹在一对圆括号中并立即被调用。
IIFE 的主要优势在于,在 IIFE 内部定义的任何“函数或变量”都无法在 IIFE 块外部访问,从而避免了全局作用域的污染。这也有助于我们高效地管理内存。
为了理解 IIFE 的概念,我们需要了解以下几者之间的区别:
- 函数声明
- 函数表达式
函数声明
让我们来看一个非常简单的“函数声明”示例:
function demoFunction(){ alert("This is the function Definition"); }
因此,理解“函数声明”的最简单方法是,它以“function”关键字开头。
函数声明相对于函数表达式的最大优势在于它们会被 JavaScript 编译器“提升”。这意味着变量可以在声明之前使用。这种行为称为“提升”,因为编译器会将变量声明移动到函数或全局代码的顶部。
提升是指 JS 声明被“提升”到其作用域的顶部。这实际上意味着变量或函数不一定在你认为它被声明的地方被声明。函数声明和变量声明始终会被提升到函数作用域或全局作用域的顶部。
可以通过这个小例子来理解:
demoFunction(); function demoFunction(){ alert("Function is already Hoisted"); }
在这里,我们可以看到用户正在尝试在编译器到达其“函数声明”之前访问“demoFunction()”。在这种情况下,函数将被执行。它将由编译器调用并显示一个警报消息。函数声明被编译器提升到作用域的顶部,因此在脚本执行过程中,在函数声明之前就可以使用它。
提升的概念不适用于函数表达式。函数表达式永远不会被提升。
函数表达式有其自身的优势,我们将在稍后进行评估。
函数表达式
“函数表达式”是指任何不以“function”关键字开头的函数定义。
定义函数表达式的另一种方法是将一个函数赋值给一个变量。
这是除上述“函数声明”语法之外的另一种创建函数的方法。
var demoFunction = function(){ alert("This is function Expression"); };
由于上述函数以“function”关键字开头,因此这是一个“函数表达式”。
上面的代码将一个函数定义赋值给变量“demoFunction”。
这意味着变量“demoFunction”现在将代表一个函数定义。
可以使用以下代码行调用该函数:“demoFunction()”。
什么是 IIFE...
IIFE (立即调用函数表达式) 是一个JavaScript 函数,它在定义后立即运行。
(function(){ alert("Function does not start with keyword "function", therefore Function Expression"); })();
这是一个简单的函数,其中函数块内的任何内容都会立即执行。
在上面的示例中,代码执行后会发生以下事件:
- 创建了一个函数实例。
- 执行了函数。
- 创建的函数被丢弃。
IIFE 执行后,IIFE 作用域中声明的变量和函数可用于垃圾回收。因此,可以高效地管理内存,并确保函数和变量不会绑定到全局作用域。
为了理解,我们可以将上述代码分解为两个部分:
- 创建函数表达式
- 调用函数表达式
第一部分:(函数表达式)
进一步分解代码,我们将得到一个包含在“括号”中的“函数表达式”。
当函数定义不以“function”关键字开头作为可执行代码行时,就称为函数表达式。
在这段代码中,我们可以看到函数定义以“(" 开头,因此它是一个函数表达式。
(function(){ alert("Function enclosed within Simple Brackets, therefore Expression"); });
这是一个简单的函数表达式。
同样,IIFE 也不以“function”关键字开头,它也是一个“函数表达式”。
所以,我们首先得到一个“函数表达式”,其中包含一些代码。
(function(){ alert("Function enclosed within Simple Brackets, therefore Expression"); });
下一步将像调用其他函数一样,使用“()”来调用“函数表达式”。
** 注意:函数表达式和函数声明之间的重要区别是:
函数声明可以被提升,但函数表达式不能被提升。
第二部分:(函数调用)
函数表达式定义后,就像调用其他函数一样,使用“()”对其进行调用。
(function(){ alert("Function Expression Invoked using () at the end"); })(); // Here the function call in made using '()'
函数表达式被调用后,函数表达式内的代码将执行。
因此,上述关于 IIFE 的讨论可以总结为:
一个立即使用“()”调用的函数表达式。
所以,在这里我们可以看到 IIFE 是一个在定义后立即调用的“函数表达式”。
分解 IIFE
因此,上面的 IIFE 代码可以重写为:
var functionExpression = (function(){ alert("Function Expression assigned to variable."); }); functionExpression();
这段代码可以这样分析:
- 创建“函数表达式”并将其存储在变量“functionExpression”中。
- 函数表达式就像任何其他函数一样被调用。
为什么我们需要 IIFE?
IIFE 的好处是:
1. 避免全局作用域被污染
创建 IIFE 的主要原因之一是避免全局作用域被污染。
让我们通过一个简单的例子来理解这一点:
(function(){ var sampleVariable = "test Variable"; var sampleVariable = function(){ alert("Function does not start with keyword "function", therefore Function Expression"); } })();
在上方的函数中,我们创建了一个“变量”和一个“函数”,这些变量和函数包含在一个 IIFE 表达式中,因此变量和函数的作用域位于 IIFE 内部。这些变量和函数不会添加到全局作用域。
当我们想要定义一些只需要在页面上执行一次的函数和变量时,可以使用 IIFE。
假设我们有一个设备,需要根据用户使用的设备设置主题。当用户登录我们的应用程序时,我们只需要检查一次设备,因为设备不会改变。在这种情况下,检测设备所需的变量和函数在执行后就不再需要了。在这种情况下,我们不想将这些变量和函数添加到全局作用域并占用浏览器空间。因此,可以将这些功能封装在 IIFE 中,一旦执行完毕,所有为此目的定义的变量和函数都可以进行垃圾回收。
2. 管理浏览器内存
如果函数只需要执行一次,如上面的例子所示,我们不需要将这些函数和变量添加到全局作用域。将它们添加到全局作用域会占用浏览器内存空间。
因此,一旦这些函数执行完毕,我们希望它们能被垃圾回收。
遇到 IIFE 时会发生以下事件:
- 创建了一个函数实例。
- 执行了函数。
- 创建的函数被丢弃。
当 IIFE 执行时,会创建、使用所需的函数和变量,并且一旦 IIFE 执行完毕,它们就可以进行垃圾回收,从而释放浏览器内存。
3. 最小化优化
IIFE 也有助于我们进行最小化。由于我们可以将值传递给 IIFE 中的参数,因此可以将每个全局对象的名称缩短为一个字母单词。
下面的示例将帮助您更好地理解:
(function(w){ alert('Window object is now renamed to "w"'); })(window);
在这里,我们可以看到“Window”对象被传递给 IIFE,“Window”对象被传递给参数“w”。因此,“window”对象现在将被引用为“w”而不是“window”,从而帮助我们进行最小化过程。
向 IIFE 函数传递参数
我们可以通过以下方式直接向 IIFE 传递参数:
var Name = "Mayank"; var Age = 27; (function(name, age){ alert("Name: " + name); })(Name, Age); Here the Arguments are enclosed within "()" brackets.
在上面的例子中,我们可以看到:
- 我们在全局级别有一个名为“Name”和“Age”的变量。
- 我们需要将这些变量传递给“IIFE”。
- IIFE 接受两个参数:“name”和“age”。
- 全局变量“Name”和“Age”被包含在函数调用括号内。
- “Name and Age”现在将作为从外部环境传递的参数在 IIFE 中可用。
**注意
请不要混淆以下 IIFE 的实现。
两者都将代表同一个 IIFE 表达式。
请注意函数调用时括号“()”的位置差异。
(function(){ alert("Name: " + name); })()
上述 IIFE 的实现与下面的实现相同。唯一的区别在于函数调用期间括号的位置。
(function(){ alert("Name: " + name); }());
IIFE 是一个出色的设计模式,提供了许多好处。尝试在您的代码中使用 IIFE 来进一步优化它。希望本文能帮助那些试图理解这个概念的人。