程序员

闭包小记

2018-03-17  本文已影响3人  chasing_dream

什么是闭包?

闭包就是能够读取其他函数内部变量的函数。
在js中,只有函数内部的函数才能读取局部变量,所以闭包就是“定义在一个函数内部的函数”。
闭包是将函数内部和函数外部链接起来的桥梁。

闭包的应用场景

循环点击事件

<body>
      <p>点我</p>
      <p>点我</p>
      <p>点我</p>
      <p>点我</p>
<script>
function init() {
        var pAry = document.getElementsByTagName("p");
        for( var i=0; i<pAry.length; i++ ) { //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
            pAry[i].onclick = function() { //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
                alert(i);  ////当找到这个i的时候,for循环已经循环完毕了,所以最终会返回4
    return arr;
            }
        }
    }
init()
</script>
</body>

为什么会出现这种情况

那是因为 i 是全局变量 污染了其他变量 出现了变量提升。

在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是4,所以这个box得到的是一个数组[4,4,4,4]。
这种情况不是我们想要的。

解决方法

在函数内部重新声明一下
变量 i 保存给在每个段落对象(p)上

function init() {   
 var pAry = document.getElementsByTagName("p");   
 for( var i=0; i<pAry.length; i++ ) {   
   pAry[i].i = i;   
   pAry[i].onclick = function() {   
    alert(this.i);   
   }   
 }   
}   

应用闭包解决

function init3() {   
 var pAry = document.getElementsByTagName("p");   
 for( var i=0; i<pAry.length; i++ ) {   
  (function(arg){     
    pAry[i].onclick = function() {     
     alert(arg);   
    };   
  })(i);//调用时参数   
 }   
}   

闭包的缺点

变量都被保存在内存中,内存消耗很大,所以不能滥用闭包。

闭包的作用

1)可以读取函数内部的变量
2)防止全局污染

闭包的特点:

a、函数嵌套函数?
b、函数内部可以引用外部的参数和变量
c、参数和变量不会被垃圾回收机制回收

有两种策略来实现垃圾回收:

标记清除 和 引用计数;

闭包的用法

创建一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象

var data= {    
    table : [],    
    tree : {}    
};    

(function(dm){    
    for(var i = 0; i < dm.table.rows; i++){    
       var row = dm.table.rows[i];    
       for(var j = 0; j < row.cells; i++){    
           drawCell(i, j);    
       }    
    }    

})(data);

思考:为什么闭包能够访问函数内部变量

function f1(){
   var n=999;
   function f2(){
   alert(n); 
   }
  return f2;
  }
  var result=f1();
  result(); // 999

正常情况下f1函数是访问不到f2函数的值,但是呢,闭包在f1函数里把f2的值给返回了f1;
那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

上一篇 下一篇

猜你喜欢

热点阅读