1 概念
- 声明一个匿名函数
- 用()把这个函数包起来(为了兼容JS语法),当然你也可以这样做
(function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来
(function(){alert('我是匿名函数')}) () //用括号把函数包起来
!function(){alert('我是匿名函数')}() // 求反,我们不在意值是多少,只想通过语法检查
+function(){alert('我是匿名函数')}()
-function(){alert('我是匿名函数')}()
~function(){alert('我是匿名函数')}()
void function(){alert('我是匿名函数')}()
new function(){alert('我是匿名函数')}()
- 然后在匿名函数后面接一对括号 (),调用这个匿名函数。

2 作用
- 只有一个作用:创建一个独立的作用域
- 这个作用域里面的变量,外面访问不到(即避免「变量污染」)
3 实战
以一个著名的面试题为例:
var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
liList[i].onclick = function(){
alert(i) // 为什么 alert 出来的总是 6,而不是 0、1、2、3、4、5
}
}
why总是6?因为 i 是贯穿整个作用域的,而不是给每个 li 分配了一个 i

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
!function(i){
liList[i].onclick = function(){
alert(i) // 0、1、2、3、4、5 ,里面的i
}
}(i) //外面的i
}
需要注意的是,外面的 i 和里面的 i 是不一样的(里面的 i 换成 j 就好理解了)
4 拓展
- 使用let 语法糖,也可以输出 0、1、2、3、4、5
var liList = ul.getElementsByTagName('li')
for(let i=0; i<6; i++){ //对,就是这里换成let
liList[i].onclick = function(){
alert(i) //0、1、2、3、4、5
}
}
- let,就是自动帮你完成了上面立即执行函数的功能而已
for(let i=0; i<6; i++){
//下面这一行你是看不到的,JS自动帮你做了
//不要使用var这个sb语法,因为var语法只有在函数里才是局部的,否则他会自动变成全局的
..........
let j=i
..........
liList[j].onclick = function(){
alert(j) //0、1、2、3、4、5
}
}
- 如果你把let放在了外面,输出的依然是6个6
let i //let放在for循环外面
for(i=0; i<6; i++){
.......
}