自执行匿名函数及其与闭包的关系
对这个感兴趣是因为看javascript 秘密花园看到闭包部分,讲到匿名包装器(自执行匿名函数)时产生了好奇,虽然之前也有接触,但是只是知道这么个东西。今天查了些资料,现在总结下,权当笔记。
函数的三种定义方式
- 第一种
1 | function addNum(x,y){ |
- 第二种
1 | var addNum = new Function('x,y','return x+y'); |
- 第三种
1 | var addNum = function(x){return x+y;} |
上面三种第一种是最常规的,调用语句可以在其之前也可以在其之后调用。第二种,大家都说不要这么用,就不要用咯。第三种是将匿名函数赋值给变量addNum,调用语句只能在其后面。
匿名函数的创建
- 第一种:就是上面第三种方式。
- 第二种:
1 | (function(x,y){ |
这里创建了一个匿名函数就是第一个圆括号包括的,第二个圆括号调用前面的匿名函数并传入参数。
自己执行的匿名函数
自执行匿名函数就是这样的:(functin{//code})();
就是上面的第二种。
自执行的原因
首先,这样的函数是不会自执行的:function{//code}();
这里是会报错的。原因是因为function在预编译阶段就会被解释,而后面的()去执行就没有执行的东西。可以理解成function{//code}
和()
是在两个不同的阶段执行,分别是预编译阶段和编译阶段。
而(function{//code})()
中第一个括号会将匿名函数转换成表达式,就不会被预编译了。就能在编译阶段立即执行了。
当然将函数转换成表达式的不只是(),还有void和~等。所以立即调用函数有下面几种:
1 | ( function() {}() ); |
呵呵,javascript就是这样的。。。
匿名函数和闭包的关系
闭包其实就是函数的嵌套(或则类的嵌套),内层能使用外层所有变量,而外层不能使用内层变量。
闭包使用匿名函数
和匿名函数有啥关系呢?咱看代码。
1 | (function(){ |
这段代码就说明了。其中foo不会执行而baz会执行。主要就是baz赋值给了window这样就暴露在了全局作用域,而foo没有则只能在匿名函数内部调用。
1 | var outer = null; |
和上面意思差不多只不过不适赋值给window而是一个外部的变量,则在外部作用域暴露了,就能调用。
这和一般的闭包自己比较吧。
在for循环中的使用
1 | for(var i = 0; i < 10; i++) { |
上面的这段代码是不会输出1,2,3,4,5…的只会打印出10个10,因为for循环早于setTimeout执行完毕,匿名函数保持对外部变量i的引用,所以就全部都是10。
这里就可以使用自执行匿名函数来解决。
1 | for(var i = 0; i < 10; i++) { |
这样就将每个单独的i当做参数传入,就不会最后都引用同一个i了。