javascript 闭包学习
1.闭包的概念:是指有权访问另一个函数作用域中的变量的函数。
2.创建闭包的常见方式:就是在一个函数内部创建另一个函数。
3.注意:闭包只能取得包含函数中任何变量的最后一个值!闭包保存的是整个变量对象而不是特殊的某个变量。
通过例子来理解:
我们有三个链接,每点击一个链接要显示,点击的是第几条!
最常见的错误写法如下:
<script>
var links = document.getElementsByTagName("a");
for(var i=0;i<links.length;i++ ){
links[i].onclick = function(){
alert("这是第"+(i+1)+"条!");
};
}
</script>
很明显如果我们有3条,点击后出来的都是3条!why?
我是这么理解的,首先,我们直接把代码写在<script></script>中,相当于省略了window.onload = function(){.........},所以links[i].onclick 相当于一个闭包(函数内部的函数)。其次,links[i].onclick = function(){.......}这是一个匿名函数,它与函数声明(function functionName(){.........})区别在于:匿名函数是执行到它时再加载,而函数声明在执行前就加载! 所以links被点击后才会去执行匿名函数function(){alert("这是第")+(i+1)+"条");}.
那为什么i+1的值都是3呢? 因为i 是在外部函数中定义的 ,它先在内部函数中找i 并没有找到,于是去外部函数找,当onload执行完后i已经变成2了,当触发onclick后传入的i值是2 所以打出来i+1的值为3!!!
正确的做法是什么呢?
《javascript高级程序设计》中给过类似这样的例子,可以看一下:
<script>
var links = document.getElementsByTagName("a");
for( var i=0;i<links.length;i++ ){
links[i].onclick = function(num){
return function(){
alert("这是第"+(num+1)+"条!");
}(i);
}
} </script>
我们来分析一下具体过程:
首先,links[i].onclick 还是给了一个匿名函数 function(num){.......}但后面加上了(i),代表什么呢? 因为function(num){...}是个匿名函数 我们没法直接调用这个函数,所以我们直接在后面给她加上(参数)代表立马执行这个匿名函数,因此i就直接传给了num.
其次,我们再看function(num){....}它的返回值返回的是一个函数,这个函数的返回结果是alert("......"); 参数是已经传入值的num,所以这么执行时正确的
原书中给的是这个例子:可以自行理解
function createFuncNew2(){
var func = new Array();
for( var i=0;i<10;i++){
func[i]=function(num){
return function(){
return num;//返回一个函数 这个函数的执行结果是num
}
}(i);
}
return func;
}
var func = createFuncNew2();
for( var i=0;i<func.length;i++){
document.write(func[i]()+"<br/>");
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <meta name="" content=""> </head> <body> <a href="#">第一条</a> <a href="#">第二条</a> <a href="#">第三条</a> <script> var links = document.getElementsByTagName("a"); for( var i=0;i < links.length; i++){ links[i].onclick = new showAlert(i); } function showAlert( num ){ return function(){ alert("这是第"+(num+1)+"条!"); }; } </script> </body> </html>
这个写法也很好, 把onclick 对应的事件写在一个showAlert(num)对象里,初次onload时就已经传递参数生成对象了,所以打印结果也是正确的!
小结: 之前写脚本时,特别依赖jquery,后来做在线测试发现,很多题要求你用原生javascript来写的!所以发现自己的javascript基础很弱啊!!!!
延伸:如果要你一个事件绑定多个函数实现上述方法,且兼容浏览器,你怎么办?因此我们要学习attachEvent和addEventListener !

浙公网安备 33010602011771号