您的位置:首页 > Web前端

立即执行函数IIFE

2017-02-24 15:24 162 查看

到底什么是IIFE?

比较以下两种方式

var foo=function(){ /*code*/}
foo();


另一种错误的方法:

function(){}(); //Unexpected token


报错原因

JS代码解释的时候,遇到function关键字会默认把它当做一个函数声明,而不是函数表达式,如果没有把它显示表达成函数表达式就会报错。 没有函数名,所以会报错

加上函数名

function foo(){}() //unexpected token


加上了名字仍然报错,我们在一个表达式后面加上括号表示这个表达式立即执行。

但如果是一个语句后面加括号,则前后没有关系。以上代码等价于:

function foo(){}
();


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

IIFE正解

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


成功,为什么? JS中,括号内部不能包含语句,当解释器对代码进行解释时,先碰到了(),然后碰到function关键字就会自动将()里面的代码识别为函数表达式而不是函数声明~~

IIFE其他更多的写法:

//常用写法
(function(){}());
(function(){})();

//括号 和 JS的一些操作符如(= && || , 等)可以在函数表达式和函数声明上消除歧义
//但是这种写法你不能交换两个的位置,解释器如果是先遇到function关键字就会报错了。
var i=fuction(){return 10;}();
true&&function(){/*code*/}();
0,function(){}();


一元运算符

!function(){}();
~function(){}();
-function(){}();
+function(){}();


new操作符

new function(){}
new function(){}() //带参数


通过以上的介绍,我们大概了解通过()可以使得一个函数表达式立即执行。

有的时候,我们实际上不需要使用()使之变成一个函数表达式,啥意思?比如下面这行代码,其实不加上()也不会保错:

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


道理还是一样,因为解释器先遇到=号了,就把后面的默认当做表达式处理了

但是好的代码规范

仍然是需要加上括号

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


为了代码的可读性。

IIFE与闭包

IIFE可以配合闭包保存状态

在IIFE里面再定义一个函数,这个函数能够引用IIFE内部的变量和参数,利用这一点我们就可以利用IIFE锁住变量的状态了。

//执行后,我们得到了想要的结果,就是因为IIFE把循环变量的每个i都锁在内存中了,
//尽管for循环结束后i的值已经变了,但是闭包的原因,其实内存中还是有对这些变量的引用存在,就是说有副本存在。
var elems=document.getElementsByTagName( 'a' );
for ( var i = 0; i < elems.length; i++ ) {
(function(lockedIndex){
elems[i].addEventlistener('click',function(e){
e.preventDefault();
console.log('i am '+lockedIndex);
},'false');
})(i)
}


其实上面的代码中的lockedIndex换成i也是可以的,因为是在两个作用域(形参在内部函数作用域,而传入的i在外部IIFE的作用域)

函数声明和函数提升

有一种值得我们注意的做法:

if(condition){
function sayHi(){
alert('Hi');
}
}else{
function sayHi(){
//other code
}
}


这么做是有问题的,在ECMAScript中是无效语法,JS引擎会修改这个错误,转换成合理的状态。 但问题是浏览器尝试修正错误的做法并不一致。

大多数浏览器返回第二个声明,直接忽略condition

但是如果使用函数表达式,那么就没问题:

if(condition){
sayHi=function (){
alert('Hi');
}
}else{
sayHi=function (){
//other code
}
}


应该使用命名函数表达式,而不是callee

//arguments.callee 在严格模式下不通过
function factoral(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
var factoral=(function f(num){
if(num<=1){
return 1;
}else{
return num*f(num-1);
}
})
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 函数 IIFE