立即调用的匿名函又被称作是立即调用函数表达式(IIFE,Immemdiataely Inovked Function Expression);它类似函数声明,但由于被包含在括号中,所以会被解释为函数表达式;是紧跟在第一组括号后面的第二组括号会立即调用前面的函数表达式(所以又叫立即执行函)
// 下面是立即执行函数例子:
// IIFE
(function () {
// 块级作用域
})
使用IIFE可以模拟块级作用域,就是在一个函数表达式内部声明变量,然后立即调用这个函数;这样就和函数作用域的变量好像在块级作用域中一样;在ECMAScript 6之前是不支持块级作用域的,所有使用IIFE模拟块级作用域是相当正常的;
但是在ECMAScript 6之后,IIFE就没有特别需要了,因为块级作用域中的变量不需要IIFE就可以实现同样的隔离
// 下面写两种不同的块级作用域:
// 内嵌块级作用域
{
let i;
for (i = 0; i <count; i++) {
console.log(i);
}
}
console.log(i); // 报错
// 循环的块级作用域
for (let i = 0; i < count; i++) {
console.log(i);
}
console.log(i); // 报错
以上代码的说了IIFE实际上的一个用途,就是可以用它锁定参数值;比如
let divs = document.querySeltorAll('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEcentListtener('click', function() {
console.log(i);
});
}
这里使用var关键字声明了循环迭代变量i,但这个变量并不会被限制在for循环的块级作用域内;因此,渲染到页面上之后,点击每个<div>都会弹出元素总数;这是因为在执行单击处理程序时,迭代变量的值是循环结束时的最终值,即元素的个数;而且,这个变量i存在于循环体外部,随时可以访问;以前,为了实现点击第几个<div>就显示相应的索引值,需要借助IIFE来执行一个函数表达式,传入每次循环的当前索引,从而”锁定“点击时应该显示的索引值:
let divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; ++i) {
divs[i].addEventListener('click', (function(frozenCounter) {
return function() {
console.log(rozenCounter);
};
})(i));
}
如果是使用ECMAScript块级作用域变量的话,就没有这么麻烦了
let divs = document.querySelectorAll('div');
for (let i = 0; i < divs.length; ++i) {
divs[i].addEventListener('click', function() {
console.log(i);
})
}
这样就可以每次让点击都显示正确的索引值了;这里事件处理程序执行的时候都会引用for循环块级作用域的索引值;这是因为在ECMAScript 6之后,新增了对for循环使用块级作用域变量关键字,在这里使用的就是let,那么循环就会为每个循环创建独立的变量,从而让每个点击处理程序都能引用特定的索引;
但是有个问题,就是如果把变量声明拿到for循环外部,就不可以执行了;下面这种写法会碰到跟在var声明变量一样的错误
let divs = document.queryCommanDindeterAll('div');
// 报错
let i;
for (i = 0; i < divs.length; ++i) {
divs[i].addEventListener('click', function() {
console.log(i);
});
}