IIFE或立即调用的函数表达式是在创建或声明后将被调用或执行的函数。创建IIFE的语法是, 将function () {}包裹在在括号()内,然后再用另一个括号()调用它,如:(function(){})()
(function() {
} ());
(function () {
})();
(function named(params) {
})();
(0 => {
});
(function (global) {
})(window);
const utility = (function () {
return {
}
})
这些示例都是有效的IIFE。倒数第二个救命表明我们可以将参数传递给IIFE函数。最后一个 示例表明,我们可以将IIFE的结果保存到变量中,以便稍后使用。
IIFE的一个主要作用是避免与全局作用域内的其他变量命名冲突或污染全局命名空间,
来个例子:
假设我们引入了一个omelibr. js的链接,它提供了一些我们在代码中使用的全局函数,但是 这个库有两个方法我们没有使用:createGraph和drawGraph,因为这些方法都有bug。我们 想实现自己的createGraph和drawGraph方法。
解决此问题的一种方法是直接覆盖:
当我们使用这个解决方案时,我们覆盖了库提供给我们的那两个方法。 另一种方式是我们自己改名称:
当我们使用这个解决方案时,我们把那些函数调用更改为新的函数名。 还有一种方法就是使用IIFE:
在此解决方案中,我们要声明了 graphUtility变量,用来保存IIFE执行的结果,该函数返 回一个包含两个方法createGraph和drawGraph的对象。
IIFE还可以用来解决一个常见的面试题:
var li = document. querySelectorAll ('. list-group > li');
for (var i = 0, len = li. length; i < len; i++) {
li[i]. addEventListener('click', function (e) {
console. log(i);
})
假设我们有一个带有list-group类的ul元素,它有5个li子元素。当我们单击单个li元素 时,打印对应的下标值。但在此外上述代码不起作用,这里每次点击li打印i的值都是5, 这是由于闭包的原因。
闭包只是函数记住其当前作用域,父函数作用域和全局作用域的变量引用的能力。当我们在全 局作用域内使用var关键字声明变量时,就创建全局变量i。因此,当我们单击li元素时, 它将打印5,因为这是稍后在回调函数中引用它时i的值。
使用IIFE可以解决此问題:
var li = document. querySelectorAll ('. list-group > 1i') ; for (var i = 0, len = li. length; i < len; i++) { (function (currentIndex) { li[currentIndex]. addEventListener('click', function (e) { console. log(currentlndex) ; }) }) (i); }
该解决方案之所以行的通,是因为IIFE会为每次迭代创建一个新的作用域,我们捕获i的值 并将其传递给currentindex参数,因此调用IIFE时,每次迭代的currentindex值都是不同 的。
Was this helpful?
0 / 0