关于闭包

来源:互联网 发布:光盘数据恢复 编辑:程序博客网 时间:2024/05/17 09:12

闭包:内层函数可以访问外层函数的变量,


当某个函数被调用时,会创建一个执行环境及相应的作用域链,然后用argument来和参数来初始化活动变量。

在作用域链中,外部的活动对象始终处于第二位,外部函数的外部函数处于第三位,直到作用域链的终点,也就是全局执行环境。

访问变量时,会从作用域链的前端开始访问。因为闭包,外部执行环境的作用域链会在函数执行后立即销毁,但是活动变量会被保存。


闭包的作用:

1.匿名自执行函数,有的函数只执行一次

2.缓存,避免调用一个处理过程很长的函数对象

3.实现封装

4.实现对象

5模仿私有变量、块级作用域


缺点:由于会保存活动变量,会导致内存泄露问题

function assignHandler(){

  var element = document.getElementById("some");

  bar id = element.id;

  element.onclick = function(){

 alert(id);

}

element.id;

}


闭包常见应用场景:

<body>

  <ul>
    <li>1</li>
<li>2</li>
<li>3</li>
  </ul>
  <script>
 /* var oUl = document.getElementsByTagName("ul")[0];
  var aLi = oUl.getElementsByTagName("li");
  for(var i = 0; i<aLi.length; i++){
    aLi[i].onclick = function(num){
return function(){
     alert("i="+i+",num="+num);
}
}(i);
  }*/
  //原始的,最爱犯的错,每次创建一个function,始终保存着外部活动对象,而他们引用的是同一个变量i,所以将每个函数的i都将是5
  function createFunction1(){
    var result= new Array();
for(var i=0; i<5; i++){
 result[i] = function(){
 return i;
 };
}
return result;
  }
  alert(createFunction1()[0]());
//创建了新的域,但仍然输出i,因为原型链中,每次创建一个function,始终保存着外部活动对象,而他们引用的是同一个变量i,此时虽然已经创建了新的域,但是i是外部函数的变量(此时已经 = 4),每次创建的function仍然会引用最后的i值
  function createFunction2(){
    var result= new Array();
for(var i=0; i<4; i++){
 result[i] = function(){
 return function(){
 return i;
 };
 }();
}
return result;
  }
  alert(createFunction2()[0]());
 //每次都会创建一个function与本身function对应的一个num,因为值传递,所以每一次创建function的时候,传入的参数i(传给num),而这个参数num是i的副本,在函数创建的时候i的值分别为0,1,2,传入的num自然也就是0,1,2。而因为参数的作用域为函数内部,所以每次都会创建一个function与本身function对应的一个num(0,1,2),且因为num是一个局部变量,所以它的值不会被下一个函数的值影响,此时虽然每次创建一个function,始终保存着外部活动对象,但是它不影响局部变量num的值
  function createFunction3(){
    var result= new Array();
for(var i=0; i<3; i++){
 result[i] = function(num){
 return function(){
     return num;
 };
 }(i);
}
return result;
  }
  alert(createFunction3()[0]());
  //总结也就是有多个num,只有一个i,所以num每次不同,而i每次都相同
  </script>
 </body>
0 0