IIFE (Imdiately Invoked Function Expression 当即执行的函数表达式)

函数声明

函数声明时必须有函数名bash

function fn(){};
复制代码

函数表达式

函数表达式中的函数能够为匿名函数,也能够有函数名,可是该函数不能直接使用,只能经过表达式左边的变量 fn 来调用闭包

var fn = function(){};
复制代码

看看二者区别

function a(){
    console.log("函数声明");
}
var b = function(){
    console.log("函数表达式"); 
}
a();   //函数申明
b();   //函数表达式
复制代码
a();   //函数声明
b();   //报错
function a(){
    console.log("函数声明");
}
var b = function(){
    console.log("函数表达式"); 
}
复制代码

为何会有这样的结果?
缘由: function a(){} 为函数声明,程序运行前就已经存在;var b = function(){} 为函数表达式,属于按顺序执行,因此 b() 会报错函数

进入IIFE (当即执行的函数表达式)

在ES5中,是没有块级做用域的概念的;咱们主要经过匿名函数的方式来块级做用域。
用做块级做用域(私有做用域)的匿名函数的语法:ui

(function() { //此处是块级(私有)做用域 })();

!function () { //此处是块级(私有)做用域  } ();   
~function () { //此处是块级(私有)做用域  } ();   
-function () { //此处是块级(私有)做用域  } ();   
+function () { //此处是块级(私有)做用域  } ();   

//这些都是当即执行的函数表达式的写法
//定义并当即调用了一个匿名函数。将函数声明包含在一对圆括号中,表示它其实是一个函数表达式。
复制代码
IIFE 写法的产生:
var a = function() { console.log("IIFE 写法的产生"); };
a();   //IIFE 写法的产生 
//咱们将一个匿名函数赋值给了一个全局变量a,而后调用了这个函数
复制代码
衍生出 IIFE 写法
(function(){
    console.log("这是一个当即执行的函数");
})();
//第一个圆括号:将匿名函数转换为函数表达式
//第二个圆括号:当即执行匿名函数(固然,你也能够设置一个函数名)
复制代码

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

经常使用实例

预期: 使用 setTimeout 循环输出 0 1 2 3 4 5code

for(var i = 0; i <= 5; i++){
    setTimeout(function timer(){
        console.log(i);
    },  i*1000);
}
//结果:1秒内输出6个6
复制代码

缘由: 超时的回调函数都将在循环完成以后当即运行。
解决方法:内存

方法一:
for(var i = 0; i <= 5; i++){
    (function(){
        var j = i;
        setTimeout(function timer(){
            console.log(j);
        }, j*1000)
    })();
}
//结果: 0 1 2 3 4 5
复制代码
方法二:
for(var i = 0; i <= 5; i++){
    (function(j){
        setTimeout(function timer(){
            console.log(j);
        }, j*1000)
    })(i);
}
//结果: 0 1 2 3 4 5
复制代码

IIFE 为每次迭代建立了新的做用域,这给了超时回调函数一个机会在每次迭代时闭包一个新的做用域。作用域

相关文章
相关标签/搜索