JS中的IIFE

IIFE

IIFE: Immediately Invoked Function Expression,翻译过来就是当即调用的函数表达式。也就是说,在函数声明的同时当即调用这个函数。javascript

普通的函数声明和函数调用java

function bar() {
    var a = 10;
    console.log(a);
}
bar(); // 函数调用
复制代码

IIFE函数声明和调用bash

(function foo(){
    var a = 10;
    console.log(a);
})();
复制代码

首先注意一点的就是IIFE函数是由一对()将函数声明包裹起来的表达式。使得JS编译器再也不认为这是一个函数声明,而是一个IIFE,即马上执行函数表达式。 可是二者达到的目的都是同样的,都是声明了一个函数而且随后调用这个函数。微信

为何要使用IIFE

若是只是为了当即执行一个函数,显然IIFE所带来的好处有限。实际上,IIFE的出现是为了弥补JS在scope方面的缺陷:JS只有全局做用域(global scope)、函数做用域(function scope),从ES6开始才有块级做用域(block scope)。对比如今流行的其余面向对象的语言能够看出,JS在访问控制这方面是多么的脆弱!那么如何实现做用域的隔离呢?在JS中,只有function才能实现做用域隔离,所以若是要将一段代码中的变量、函数等的定义隔离出来,只能将这段代码封装到一个函数中。markdown

为调用一次的函数达到做用域隔离、命名冲突、减小内存占用问题。闭包

块级做用域

在ES5中是没有块级做用域的概念。只有全局做用域和函数做用域函数

for (var i = 0; i< 10; i++) {
    console.log(i);
}
console.log(i); // 10
复制代码

这个地方能够看出for循环中的变量i是一个全局变量,在for循环执行完毕后这个i仍是能够访问到的。i并无被销毁spa

块级做用域也能够称为私有做用域。也就是说只在for循环的语句块中有定义,一旦循环结束,变量i就会被销毁,而在ES5中咱们主要使用匿名函数【IIFE】的方式来达到块级做用域的效果。翻译

IIFE实现做用域隔离
// 函数声明语句写法
function test() {};
test();

// 函数表达式写法
var test = function(){};
test();
复制代码

[注意]javascript引擎规定,若是function关键字出如今行首,一概解释成函数声明语句;而函数声明后面是不能跟圆括号的(匿名函数是函数声明的一种)。然而,函数表达式的后面能够跟圆括号。因此能够将函数声明转换成函数表达式。 在当即执行函数中,定义的变量会在当即code

因此,解决方法就是不要让function出如今行首,让引擎将其理解成一个表达式 最经常使用的几种办法

(function(){
    console.log('123');
}());

(function(){
    console.log('123');
})();

(function foo(){
    console.log('123');
})();
复制代码
分号

对于当即执行函数末尾的;分号,最好加上,由于若是不加,遇到两个都是用括号()包裹执行的IIFE时,就会遇到问题。

(function(){
    console.log('a');
})()

(function(){
    console.log('b');
})()
复制代码

这一段代码只有a能够显示出来,b会报错

TypeError: (intermediate value)(...) is not a function

不加分号,上面的内容会被JS理解为:

(function(){
    console.log('a');
})()(function(){
    console.log('b');   
 })()
复制代码

也就是说,a匿名函数执行后,没有;的隔断,后面的b当即执行函数与a合成了一个函数。执行到输出完a时,没有reutrn,后面的()至关于对undefined进行了执行,因此报错。

咱们能够这样修改

(function(){
    console.log('a');
})()

(function(){
    console.log('b');
}())

复制代码

这样修改后,a,b都会显示出来,可是一样会报错, 还有其余的修改方式,可是我建议加上;分号避免报错。

IIFE的优势

  • 建立块级(私有)做用域,避免了向全局做用域中添加变量和函数,所以也避免了多人开发中全局变量和函数的命名冲突。
  • IIFE中定义的任何变量和函数,都会在执行结束时被销毁,这种作法能够减小闭包占用的内存问题,由于没有指向匿名函数的引用。只要函数执行完毕,就能够当即销毁其做用域链了。

欢迎关注微信公众号

相关文章
相关标签/搜索