欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

立即执行函数(IIFE) 立即调用函数表达式 有大用

IIFE(立即执行函数)是英文Immediately-invoked function expression的缩写。
在平时我们定义一个函数通常是这样的:

function a() {...};

我们也可以将一个匿名函数赋值给了一个全局变量a:

var a = function() {...};


然后我们这么来调用它:

a();


既然这样,咱们是不是可以不用定义这个全局变量直接来执行这个匿名函数,像这样:

function() {...}();

//SyntaxError: function statement requires a name


结果报错了。这是因为在javascript代码被解析时,当遇到function关键字时,会默认把它当做是一个函数声明,而不是函数表达式,如果没有把它显式的表达成函数表达式,就报错了,因为函数声明需要一个函数名,而上面的代码中函数没有函数名。
如果我们给它一个函数名,然后加上()立即调用,像这样:

function foo() {...}(); // SyntaxError: Unexpected token )

结果还是报错了。这是因为如果是在一个语句后面加上括号,这个括号就变成了一个分组操作符,用来控制运算中的优先级(小括号里的先运算)。所以以上代码等价于:

function foo(){...}
(); // SyntaxError: Unexpected token )

相当于先声明了一个叫foo的函数,之后进行()内的表达式运算,但是()(分组操作符)内的表达式不能为空,所以报错。
那下面咱们一起看看这个IIFE:

(function(){...}());


这样写代码能过顺利执行不报错,这是因为当解析器对代码进行解析的时候,先碰到了(),然后碰到function关键字就会自动将()里面的代码识别为函数表达式而不是函数声明。当然你也可以在function后面加个函数名,不过函数名在这里没有意义,因为整个函数在执行时就立即调用了。
IIFE还有以下几种写法:

//常用方式

(function(){ /* code */ }()); // 推荐写法

(function(){ /* code */ })();

//在前面加上一元运算符,这样也可以使解析器解析成函数表达式,而且还可以省略一个字节

!function(){ /* code */ }();

~function(){ /* code */ }();

+function(){ /* code */ }();

-function(){ /* code */ }();

//也可以new一个方法

new function(){ /* code */ };

new function(){ /* code */ }();


如果你在写下面这段代码时:

var i = function(){ return 10; }();


这样不会报错,但是建议加上外():

var i = (function(){ return 10; }());


因为我们在阅读代码的时候,如果function内部代码量庞大,我们不得不滚动到最后去查看function(){}后是否带有()来确定i值是个function还是function执行后的值。
像普通的函数传参一样,立即执行函数也能传参数:

for (var i = 0; i < 10; i++) {
    (function(i) {
        setTimeout(function() { console.log(i); }, 100 * i);
    })(i);
}


IIFE还具有私有性,如果定义一个普通函数:

function foo(){

    var i =195;

}

console.log(i);
//195


这样是能获取到值的,因为没有块级作用域的概念,在foo中声明的 i 变量实际上是一个全局变量,因此可以在全局环境中访问的到。
块级作用域,也可以称为私有作用域,在ES5中,主要就是通过匿名函数的方式来实现块级作用域:

(function(){

    var i =195;

})()

console.log(i);

// Uncaught ReferenceError: i is not defined


总结
1.IIFE能够避免向全局作用域中添加变量和函数,因此也避免了多人开发中全局变量和函数的命名冲突。
2.IIFE中定义的任何变量和函数,都会在执行结束时被销毁。这样可以减少闭包占用的内存问题。


来自  https://blog.csdn.net/cuishizun/article/details/81672371


普通分类: