了解过js的同学基本上都遇到过()()这种方式的函数体。一开始我也不懂这是啥,没见过啊,这特么到底是什么玩意?具体深入了解后,才知道这是匿名函数直接执行的一种写法。看过某些帖子上有一个经典的例子,在此记录下来。
这种方式叫函数的闭包(closure),可以让匿名函数立即被执行(最后面的那对括号就是让上面定义的匿名函数立即执行的秘密),这种闭包有以下几个优势或特点:
1. 减少了全局变量的个数,可以有效减少命名冲突
原因是包在里面的变量对于外面来说是不可见的,他们的作用域近局限在匿名函数的函数体内
2. 这种方式可以保存闭包外面的变量的状态,这个特点还是举个例子比较易懂:
function fn() { for(var i=0 ; i<2; i++) { //(function(){ var backup = i; setTimeout(function() { alert(backup); }, 2000); //})(); } } fn();
上面代码的for循环一共两次,我们本来的目的是每隔两秒钟把每一次循环的索引(也就是i)输出,我们期待它应该输出:0和1,但是实际输出结果却是两次都是1
使用了闭包之后,我们会把循环中每一次i值的状态都保存下来,如下代码所示:
function fn() { for(var i=0 ; i<2; i++) { (function(){ var backup = i; setTimeout(function() { alert(backup); }, 2000); })(); } } fn();
这次我们得到了正确的结果:0和1。因为闭包引用的是父函数范围内的最终值。
括号表达式,写起来精简,另外匿名函数就执行了,不过这么写函数就没办法通用了。
最后再来看看下面这种写法,传参的一种形式。
function f() { var a = []; var i; for(i = 0; i < 3; i++) { a[i] = (function(i){ return function(){ alert(i); return i; } })(); } return a; } var a = f(); a[0]();//undefined a[1]();//undefined a[2]();//undefined --------------------------- function f() { var a = []; var i; for(i = 0; i < 3; i++) { a[i] = (function(x){ return function(){ alert(x); return x; } })(i); } return a; } var a = f(); a[0]();//0 a[1]();//1 a[2]();//2
上面的代码可以得出一个结论。js中,表达式立即执行()()的这种写法可以表示为(匿名表达式)(需要传入的参数),即(function(arg1,arg2,...){})(arg1,arg2,...),能表达这种写法的最简便的代码如下:
(function(a,b,c){ alert(a); alert(b); alert(c); })(1,2,3); //打印结果 //1 //2 //3