立即执行函数表达式
IIFE(Immediately-invoked function expression)
我们知道,在javascript(ES5)中,是没有块级作用域的概念的。看一个例子
for (var i = 0; i < 5; i++) {
}
console.log(i); //5
因为没有块级作用域的概念,因此,在 for 循环中声明的 i 变量实际上是一个全局变量,因此可以在全局环境中访问的到。
块级作用域,也可以称为私有作用域。也就是说只在for循环的语句块中有定义,一旦循环结束,变量 i 就会被销毁。而在ES5中,我们主要通过匿名函数的方式来块级作用域。
用作块级作用域(私有作用域)的匿名函数的语法:
(function() {
//此处是块级(私有)作用域
})()
以上代码定义并立即调用了一个匿名函数。将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式。看看这种写法是如何产生的
var a = function() {
console.log(123);
};
a(); //123
我们将一个匿名函数赋值给了一个全局变量a,然后调用了这个函数
当然也可以这样调用函数
var a = function() {
console.log(123);
};
a(); //123
既然这种方式可以立即执行一个函数,那也就意味着将匿名函数赋值给一个变量就完全没有意义了。
如果这样实现:
function() {
console.log(123);
}();
//SyntaxError: function statement requires a name
这段代码会导致语法错误,是因为Javascript将function关键字当作一个函数声明的开始,而函数声明后面是不能跟圆括号的(匿名函数是函数声明的一种)。然而,函数表达式的后面可以跟圆括号。要将函数声明转换成函数表达式,
只要像下面这样给它加上一对圆括号即可。
//函数名没意义,所以使用匿名函数
//第一个圆括号:将匿名函数转换为函数表达式。
//第二个圆括号:立即执行匿名函数
(function() {
console.log(123);
})()
//当然,你也可以给一个函数名,不过函数名在这里没有意义,因为整个函数在执行时就立即调用了。
(function keith() {
console.log(123);
})()
总结
了解了以上内容后,总结一下IIFE的优先:
1.创建块级(私有)作用域,避免了向全局作用域中添加变量和函数,因此也避免了多人开发中全局变量和函数的命名冲突
2.IIFE中定义的任何变量和函数,都会在执行结束时被销毁。这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了
应用
立即执行函数表达式主要跟闭包扯上关系,可以看看这两篇文章。
传送门:
深入理解javascript函数参数与闭包(一)
深入理解javascript闭包(二)