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/>");
         }

 

 

 
ps: 网络上有大神给过别的正确实现方法,也很好,学习一下:
<!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 !

 

posted @ 2014-04-07 11:27  Ann大然  阅读(83)  评论(0)    收藏  举报