一、what?
可以理解为:立即调用的函数表达式
常见的两种形态
//形态一
(function(){
//do something here;
})();
//形态二
!function(){
// do something
}();
那么问题来了:
请问形态二可以执行是什么原因,为什么去掉符号就会有语法错误?
so:
first:我们先理解一下括号的含混使用,
- 可以做执行操作
- 可以分组
(1)它可以用来执行一个函数:
eg:go();
(2)还可以做为分组运算符来分组。
(function(){})()
黄色括号是分组运算符,对内部的 function(){}进行整合
后边的红色括号是执行意思
整体结构就是(表达式)()
到这里我们差不多就可以理解第二种形态了
我们把形态二改动成下边这样,更容易理解
;( function() {}() )
这里外部的黄色大括号就是一个分组运算符,
里边的红色括号用做执行,
前边的“;”只是一个引导
黄色括号最好是加上,这样逻辑更清晰
所以那些匿名函数附近使用括号和一元运算符的惯用法,就是来引导解析器,指明运算符附近是一个表达式。
按照这个理解,我们还可以举出很多例子:
( function() {}() );
( function() {} )();
[ function() {}() ];
~ function() {}();
! function() {}();
+ function() {}();
- function() {}();
二、how?
一些样例:
(1) 用闭包实现私有成员
//私有成员,状态函数
var nextId = function() {
var id = 1
return function() {
id++;
console.log(id);
return id;
}
}();
这里需要注意,因为nextId是返回的一个函数,这个函数并没有后边的执行();
所以它要执行还需要加()
nextId();//2
nextId();//3
nextId();//4
//通过条件判断做不同操作
var go = function(param) {
//console.log(param); //输出1
return function() {
console.log(param);
if (param=="1") {
console.log("do impl1")
} else {
console.log("do impl2")
}
}
}("1");
go();
(2) 常量或对象属性初始化
object.prop = (function() {
var o = {}
o['__created__'] = Date.now()
o['name'] = object.otherProp
return o
})()
(3) 运行一次的模块
(function() {
var module = require('module')
module.setup()
module.run()
})()
eg:jquery中的$(function(){})
(4)解决循环陷阱(引用自nodejs开发指南)
上面代码在for循环体中建立了匿名函数,将循环迭代变量i作为函数的参数传递并调用。由于运行时闭包的存在(在匿名函数中存在内部函数)
该匿名函数中定义的变量,在他内部函数fs.redFile执行完毕之前都不会释放,所以里边用到的实例就不会被释放
PS1:
如果不这样做,结果就是“i”已经变成3了,回调的第一个还没有返回,readfile输出的时候都是files[3],显示为"undefined"
PS2:
当然比较简单的方法也可以在最外层循环处使用forEach,绕过使用“i”
POST:https://www.zhihu.com/question/20249179