了解过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