一 历史
JavaScript其实是一门奇异的语言,TA的一大特性是没有块级作用域
for(var i=0;i<10;i++){}
console.log(i)
大家猜测下值是多少?
答案是 10, 虽然我们在一个块内申明了变量,但i却是在全范围内起作用的,所以就引入了匿名函数
function(){var i=0;...
}
以函数的作用域来限定变量作用域
二 立即执行匿名函数
当然,还立即执行的匿名函数
(function(){do sth.....
})()
第一次看到感觉真tm古怪,还tm要这样写,太tm古怪了,我们可以这样看:
定义一个虚拟变量 var foo = function(){...}
然后foo要执行,所以就
foo() = (function(){do sth.....})()
好了,匿名函数就立即执行了
三 循环中的匿名函数
大家看下面一段代码
function foo(){var arr = [];for(var i =0;i<5;i++){arr[i] = function(){//console.log(i) 来看看什么时候运行return i; //定义函数时i的值并没有初始化,指向函数外的i,因此,当匿名函数运行时,这个值就指向最大的i了}}return arr;
}var a = foo(); //arr的赋值没有被执行
for (var i = 0; i< 5 ;i++){alert(a[i]());
}
有兴趣的不妨运行一下,答案是5个5,发生什么事了呢?
我们在对arr赋值的时候:
arr[i] = function(){return i; }
函数里面的i是没有分配具体的值的,它指向了最外层的i,而运行时才会赋值,所以,它就是最大的5了,再看一个例子
var arr = document.getElementsByTagName("p");for(var i = 0; i < arr.length;i++){arr[i].onclick = function(){alert(i);}}
这是一个DOM的onclick事件,当点击的时想能够弹出不同的i值,实际上是无法实现的,所以,必须使用匿名函数的立即执行来限定作用域
var arr = document.getElementsByTagName("p");for(var i = 0; i < arr.length;i++){(function(j){arr[j].onclick = function(){alert(j);}})(i)}
四 循环中的异步函数
这样一段代码
for(var i=0;i<n;i++){ajax(i,function(....)) //这里是一个异步调用,还有request,http等
}
这里i会是最大值,为何呢?因为这是一个异步函数,而非同步立即返回的函数,此时由于js奇怪的单线程机制,会待同步全部结束后再运行异步的代码,所以i始终是最大值,那么要用什么方法解决呢?是的,加一个闭包。
这里留下一个问题,如果写成这样,你觉得可以么
for(var i=0;i<n;i++){var j={a:i}ajax(j.a,function(....))
}
总之,js真是一门奇异的语言