【JS】自执行函数
目录立即调用的函数表达式一、函数的声明与执行二、 ()的问题三、自执行函数表达式四、自执行函数的应用立即调用的函数表达式在JavaScript中,会有自执行匿名函数:(function () {/*code*/} ) (),Self-executing anonymous function。一、函数的声明与执行函数声明与执行:// 声明函数fun0function fun0(){console.l
目录
立即调用的函数表达式
在JavaScript中,会有自执行匿名函数:(function () {/*code*/} ) (),
Self-executing anonymous function。
一、函数的声明与执行
函数声明与执行:
// 声明函数fun0
function fun0(){
console.log("fun0");
}
//执行函数fun0
fun0(); // fun0
除了上面这种最常见的函数声明方式,还有变量赋值方式的,如下:
// 声明函数fun1 - 变量方式
var fun1 = function(){
console.log("fun1");
}
// 执行函数fun1
fun1(); // fun1
二、 ()的问题
//demo1:
function(){
console.log("fun");
}();
// 以上会报错 line1:Uncaught SyntaxError: Unexpected token (。
// demo2 加上函数名看看:
function fun2(){
console.log("fun2");
}();
// 以上会报错 line3:Uncaught SyntaxError: Unexpected token )。
// demo3 给它加个实参(表达式):
function fun3(){
console.log("fun3");
}(1);
// 不会报错,但不会输出结果fun3。
分析:
demo1中
function
是声明函数关键字,若非变量赋值方式声明函数,默认其后面需要跟上函数名的。
demo2中
声明函数的结构花括弧后面不能有其他符号(比如此处的小括弧)。
demo3中
以上代码相当于在声明函数后,又声明了一个毫无关系的表达式。
三、自执行函数表达式
想要解决上面问题,可以采用小括弧将要执行的代码包含住(方式一),如下:
// 方式一
(function fun4(){
console.log("fun4");
}()); // "fun4"
分析:因为在JavaScript语言中,()
里面不能包含语句(只能是表达式),所以解析器在解析到function
关键字的时候,会把它们当作function表达式,而不是正常的函数声明。
除了上面直接整个包含住,也可以只包含住函数体(方式二),如下:
// 方式二
(function fun5(){
console.log("fun5");
})();// "fun4"
写法上建议采用方式一,但是方式二比较常。
注意:
除了上面()
小括弧可以把function
关键字作为函数声明的含义转换成函数表达式外,JavaScript的&&
与操作、||
或操作、,
逗号等操作符也有这个效果。
true && function () { console.log("true &&") } (); // "true &&"
false || function () { console.log("true ||") } (); // "true ||"
0, function () { console.log("0,") } (); // "0,"
// 此处要注意: &&, || 的短路效应。即: false && (表达式1) 是不会触发表达式1;
// 同理,true || (表达式2) 不会触发表达式2
如果不在意返回值,也不在意代码的可读性,我们甚至还可以使用一元操作符(!
~
-
+
),函数同样也会立即执行。
还可以使用new
关键字:
// 注意:采用new方式,可以不要再解释花括弧 `}` 后面加小括弧 `()`
new function () { console.log("new"); } //"new"
// 如果需要传递参数
new function (a) { console.log(a); } ("zahngsan"); //"zahngsan"
四、自执行函数的应用
for
循环里面通过延时器输出索引 i
for( var i=0;i<5;i++){
setTimeout(function(){
console.log(i);
}
,0);
}
// 输出结果 5 5 5
上面代码中设定了一个
setTimeout
,那浏览器会在合适时间(此处是0ms后)把代码插入任务队列,等待当前的for
循环代码执行完毕再执行。(注意:setTimeout 虽然指定了延时的时间,但并不能保证执行的时间与设定的延时时间一直,是否准确取决于 JavaScript 线程是拥挤还是空闲。
把setTimeout
代码包含在匿名自执行函数里面,就可以实现“锁住”索引i
,正常输出索引值。
for( var i=0;i<5;i++){
(function(lockedIndex){
setTimeout(function(){
console.log(lockedIndex);
}
,0);
})(i);
}
// 输出 "1,2,3,4,5"
分析:尽管循环执行结束,
i
值已经变成了5。但因遇到了自执行函数,当时的i
值已经被lockedIndex
锁住了。也可以理解为 自执行函数属于for循环一部分,每次遍历i
,自执行函数也会立即执行。所以尽管有延时器,但依旧会保留住立即执行时的i
值。
ES6中let解决办法:
for( let i=0;i<5;i++){
setTimeout(function(){
console.log(i);
}
,0);
}
// 输出 "1,2,3,4,5"
分析:let为ES6中新增块级作用域
更多推荐
所有评论(0)