立即执行函数

86 阅读3分钟

想让一个函数只执行一次,让函数执行完就销毁。把这种函数称为针对初始化功能的函数。

立即执行函数的特点是执行完后将函数立即释放

语法:使用一对括号将匿名函数包裹起来,再在匿名函数最后加上一对小括号。

//语法一:
(function (){}())
//语法二:
(function (){})()

//W3C推荐使用第一种

立即执行函数除了能够执行完后立即销毁的区别,其他的和函数没有任何区别。

立即执行函数也能经历预编译,能够产生执行期上下文。

function test(){
    console.log(1);
}()
//这样将会报语法错误 SyntaxError: Unexpected token ')'

function test(){
    console.log(1)
}
test()  //1

为什么会报错呢?意思不是一样的吗?

首先,只有函数表达式才能被执行符号执行

let test = function(){
    console.log(1)
}()
//所以这样能够被执行

能被执行符号执行的函数表达式,通常会忽略名字,上述的test则为undefined,基本上就是立即执行函数。

image.png 或者可以隐式转换

+function test(){
    console.log(1);
}()
//在前面加上+号,相当于隐式转换为数字,就变成表达式了,则后面直接加上括号便能运行且不报错。
//+ - !都可以变成表达式

括号算数学运算符,将函数放入括号中,使函数变为表达式。然后就能够直接被执行了。

(function test (){})()
//小括号放里放外都行,最终的结果都是变为表达式。

这样的函数表达式,test最终都会为undefined,那干脆就直接不写,最后变为立即执行函数。

还有一个小例子

function test(a,b){
    console.log(a+b);
}(1,2)
//这个理论上是不能执行的
//但是系统认为,最后的括号是分开的

function test(a,b){
    console.log(a+b)
}

(1,2)
//所以不会报错,但也不会执行

注意:

当多个立即执行函数执行的时候,函数之间需要加分号隔开。不然会报错,会以为未结束。

(function (){
    console.log(1);
})();

(function (){
    console.log(2);
})();

立即执行函数的作用:防止变量污染。

function test(){
    let arr = []
    for(var i = 0;i<10;i++){
        arr[i] = ()=>{
            console.log(i);
        };
    }
    return arr
}
let myArr = test()
for(let i = 0;i<10;i++){
    myArr[i]()  //输出十个10
}

因为arr里存入的是函数体,而函数体没有执行,所以i没有赋值

后面在外部输出的时候就是在作用域下去找i,作用域里的i已经变成10了

要想解决这个问题,并且不使用let关键字的情况下,可以使用立即执行函数

function test(){
    let arr = []
    for(var i = 0;i<10;i++){
        ((j)=>{
            arr[j] = ()=>{
                console.log(j);
            }
        })(i)
    }
    return arr
}
let myArr = test()
console.log(myArr);
for(let i = 0;i<10;i++){
    myArr[i]()
}
// 因为每个函数都有自己的AO,每个AO的j的值都不一样,当执行的时候,读取的是被保存出来的当前小函数的AO的j

小结

立即执行函数的特点是让函数执行完后就立即销毁

立即执行函数的语法是使用一堆括号将匿名函数包裹起来,再在匿名函数后面加让一对小括号。最后要加上分号。

立即执行函数的作用是防止变量污染。