进击的 JavaScript(五) 之 马上实行函数与闭包

前面的闭包中,提到与闭包类似的马上实行函数,觉得二者照样比较轻易弄混吧,严格来说(因为犀牛书和高程对闭包的定义差别),马上实行函数并不属于闭包,它不满足闭包的三个前提。

一、圆括号运算符

  圆括号运算符也叫分组运算符,它有两种用法:假如表达式放在圆括号中,作用是求值;假如跟在函数背面,作用是挪用函数

  把表达式放在圆括号当中,将返回表达式的值

console.log((1+2)); // 3

  将函数放在圆括号中,会返回函数自身。假如圆括号紧跟在函数的背面,就示意挪用函数,即对函数求值

console.log((function testa(){return 666;}));
// function testa(){return 666;}

console.log(function testa(){return 666;}());
// 666

注重:圆括号运算符不能为空,不然会报错

();//SyntaxError: Unexpected token )

因为圆括号的作用是求值,假如将语句放在圆括号当中,就会报错,因为语句没有返回值

(var a = function(){return 666});
// SyntaxError: Unexpected token var

二、函数声明

运用 function 关键字建立一个函数,而且背面带有函数名,叫函数声明。

function testa(){}

三、匿名函数

那末运用 function 关键字建立的函数不带函数名呢? 那就是匿名函数了。

function (){}

四、函数表达式

那末把匿名函数赋值给一个变量呢?那就是函数表达式了。

var testa = function (){}

实在呢,函数表达式的基础地点,就是阻挠了js引擎把 function建立的函数 看成函数声明来剖析。下面再详说。

五、马上实行函数(IIFE)

那末马上实行函数呢?

function定义函数以后,马上挪用该函数。这类函数就叫做马上实行函数,全称为马上挪用的函数表达式IIFE(Imdiately Invoked Function Expression)

1、在本系列进击的 JavaScript(三)中到过,代码实行时,会先对函数声明的函数 举行剖析(函数声明提拔),而函数表达式,当逐行实行到它时,才会剖析。

2、正因为函数声明的提拔,致使函数声明不能马上实行。因为,函数声明时,js只会剖析到大括号(})就终了了,假如背面有(),只是一个圆括号运算符。

function testa(){
    console.log("testa")
}("666")

//"666"
//假如背面是一个空的圆括号,会报错,上面提到过。

所以,不知道,你有无发明,函数声明的函数,背面能够不必分号(;)分开,也能够一般实行,而函数表达式的背面就必须加分号,不然会报错。你能够本身写个小栗子考证下。

3、匿名函数是不能零丁写的,所以就提不上马上实行了。

function (){}
//Uncaught SyntaxError: Unexpected token (

零丁写匿名函数,是会报错的,js引擎 会把它看成函数声明来剖析,而函数声明就必须要有个函数名,所以会报错。
所以,你一般看到运用匿名函数,都是看成参数通报的,或许把匿名函数转为函数表达式。

4、因而,只要函数表达式能够马上实行

var testa = function (){
    console.log("testa")
}()
//"testa"

上面提到过,函数表达式,就是阻挠了js引擎把 |用function建立的函数| 看成函数声明来剖析。

注:javascript引擎划定,假如function关键字涌如今行首,一概诠释成函数声明语句。

所以,解决方法就是不要让function涌如今行首,让引擎将其明白成一个表达式。

//经常使用的两种,运用圆括号运算符
(function(){console.log("666")})()
(function(){console.log("666")}())

//一元运算符写法
!function(){console.log("666")}()
+function(){console.log("666")}()
-function(){console.log("666")}()
~function(){console.log("666")}()

都是都能够把函数声明 转为 函数表达式,也就是阻挠了把其看成函数声明剖析。

六、马上实行函数在闭包中的运用

1、马上实行函数能合营闭包保留状况。

来看下 上节内容中闭包的例子:

function makeClosures(i){    
    var i = i;  
    return function(){
        console.log(i);     
    }
}

for (var i=1; i<=5; i++) {
    setTimeout(makeClosures(i),i*1000);  
}
//1
//2
//3
//4
//5

如今,我们来应用马上实行函数来简化它:

for (var i=1; i<=5; i++) {
    setTimeout((function(i){
        return function(){
            console.log(i);
        }
    })(i),i*1000);
}

第一个匿名函数实行终了后,返回了第二个匿名函数。第二个匿名函数被当作setTimeout 的第一个参数传入进去。因为 setTimeout函数实行了5次,所以马上实行函数里每次都邑返回了一个没有被实行的匿名函数,(这里就是返回了5个匿名函数),每一个匿名函数内部保留着每次传进来的i值,因而,每一个i 都是不一样的,所以,就得到了想要的效果

2、马上实行函数合营闭包 模块化中运用

(function(){
    var meg = "hello zdx";
    
    function say(arg){
        arg = arg || meg;
        console.log(arg)
    }
    
    window.say = say;
})(window)

window.say();

//"hello zdx"

起首马上实行函数,它是个匿名函数,你是得不到它的函数援用,如许,就避免了全局变量污染。其次,因为函数作用域的划定规矩,在匿名函数外部是接见不了函数内的变量,函数等的。所以,也经经常使用马上实行函数模仿块级作用域。

    原文作者:周大侠啊
    原文地址: https://segmentfault.com/a/1190000015644558
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞