原文链接:[译] JavaScript:立即执行函数表达式(IIFE)
(一) JavaScript 中的圆括号
JavaScript 中的圆括号不能包含声明,当我们将函数声明放在一个圆括号里面时,语法分析器会将其表达成一个函数表达式。
- 当圆括号出现在匿名函数的末尾想要调用函数时,它会默认将函数当成是函数声明。
- 当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明。
因此,实现一个立即执行函数的方式很简单:
(1) 这里将函数声明放在圆括号里,表示表达式,后面的圆括号表示立即执行。
(function(){/* code */}());
(2) 如果我们是这样写的话,会报错,因为这是一个函数声明。
function(){ /* code */}();
(3) 当然,如果将其改为表达式的写法是可以的
var foo = function(){console.log(1)}()
(二) 保存闭包状态
闭包: 任何一个定义在函数内部的函数都可以使用外面函数传递进来的参数和变量。立即执行函数一个最显著的优势是就算它没有命名或者说是匿名,函数表达式也可以在没有使用标识符的情况下被立即调用,一个闭包也可以在没有当前变量污染的情况下被使用。
// 它的运行原理可能并不像你想的那样,因为`i`的值从来没有被锁定。
// 相反的,每个链接,当被点击时(循环已经被很好的执行完毕),因此会弹出所有元素的总数,
// 因为这是 `i` 此时的真实值。
var elems = document.getElementsByTagName('a');
for(var i = 0;i < elems.length; i++ ) {
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + i)
},false);
}
// 而像下面这样改写,便可以了,因为在IIFE里,`i`值被锁定在了`lockedInIndex`里。
// 在循环结束执行时,尽管`i`值的数值是所有元素的总和,但每一次函数表达式被调用时,
// IIFE 里的 `lockedInIndex` 值都是`i`传给它的值,所以当链接被点击时,正确的值被弹出。
var elems = document.getElementsByTagName('a');
for(var i = 0;i < elems.length;i++) {
(function(lockedInIndex){
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + lockedInIndex);
},false)
})(i);
}
//你同样可以像下面这样使用IIFE,仅仅只用括号包括点击处理函数,并不包含整个`addEventListener`。
//无论用哪种方式,这两个例子都可以用IIFE将值锁定,不过我发现前面一个例子更可读
var elems = document.getElementsByTagName( 'a' );
for ( var i = 0; i < elems.length; i++ ) {
elems[ i ].addEventListener( 'click', (function( lockedInIndex ){
return function(e){
e.preventDefault();
alert( 'I am link #' + lockedInIndex );
};
})( i ),false);
}
注:立即执行函数既可以是命名函数,也可以是匿名函数。