你一定看得懂的 —— 闭包

Js 是一门完整的面向对象语言,同时也有 函数式语言特性。其中 就有 闭包和高级函数。

听到 闭包,你会想到什么?
闭包是什么?
闭包的作用是什么?
为什么要用闭包,它为我解决 什么问题?

1. 它是js一种语言特性,它 跟 变量的作用域和垃圾      回收机制相关
2 . 能够读取其它函数 内部变量的函数  称为闭包;
3. 在外部读取引用函数内部变量,外部

闭包

它是一个很难又必须征服的概念。它的形成 与变量的作用域 以及生存周期密切相关。

1. 变量的作用域
变量的作用域 指的是变量的有效范围。
在函数中声明一个变量的时候:①没有关键字 var ,这个变量就会变成 全局变量。
                                                  ②有关键字 var,就是 局部变量。只有在函数内部才能访问这个                                                       变量,函数外部 访问不到。

var func = function ( ) {
      var a =1;    //  局部变量
      alert ( a ) ;
}
func ( )   //   1
alert ( a )   //  a is not defined

var func = function ( ) {
      a = 1 ;     // 全局变量
      alert( a ) ;
}
func( );  //  1
alert( a ) //  1

在JS中,函数可用来创造函数作用域。此时的函数像一层半透明的玻璃,在函数里面可以看到外面的变量。而在函数外面却看不到函数里的变量。
这是因为,在函数中搜素一个变量的时候,如果该函数内并没有声明这个变量,那么此次的搜索过程 会随着代码的执行环境创建的作用域链 往外逐层搜索,直到全局对象为止。
变量的搜索是从内到外 而非从外到内

var a = 1 ;
var func1 = function ( ) {
      var b = 2 ;
      var func2 = function ( ) {
            var c = 3 ;
            alert ( b) ;    //  2
            alert ( a );   //1
     }
     func2( );
     alert( c );  //  c is not defined;
}
func1 ( );

2.变量的生命周期
提到生命周期,不得不提 JS 具有的自动垃圾收集机制
简单来说,就是 销毁掉环境中无用的变量,完成内存清理工作,从而回收它们所占用的空间。
具体来说1:执行环境会负责管理代码执行工程中使用的内存。在编写JS时,开发人员不用再关心内存的使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔周期性执行这一操作。
具体来说2: 局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在堆或栈内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行 结束。此时,局部变量就没有存在的必要了,因此释放掉它们的内存以供将来使用。
对于全局变量来说,它的生命周期当然是永久的。对于函数内部 的局部变量来说,当退出函数时,这些变量即失去了它们的价值,它们都会随着函数调用的结束而被摧毁

var func1 = function ( ) {
      var a = 1 ;
      a++ ;
      alert( a ) ; 
}
func1 ( ) ;    //  2;
func1 ( ) ;   //   2;
func1 ( ) ;   //   2;

var func2 = function ( ) {
      var a = 1 ;
      return function ( ) {
            a++;
            alert( a );
      }
}

var f = func2 ();
f ( ) ;    //  2
f ( ) ;    //  3
f ( ) ;   //   4

执行函数func1时,每次执行都 弹 2。说明每次执行,a重新被赋值 1; 即每次调用函数结束后, 变量 a 在堆或栈里存的值被销毁(赋值null)。

执行函数func2时,数字依次增加。说明局部变量a并没有在函数执行后被销毁。 而是存活在某个地方。这是因为当执行 var f = func2( ) 时,f 返回了一个匿名函数的引用,这个引用可以访问到 func2 () 被调用时产生的环境,而局部变量 a 一直处在这个环境里。既然 局部变量还能被外界访问,这个局部变量就有了不被销毁的理由。 

var nodes = document.getElementsByTagName('div');
for(var i = 0; i < nodes.length; i++) {
     nodes[i].onclick = function () {
               alert( i )
      }
}

无论点击哪个div ,最后弹的都是 5.这是因为 onclick 是异步触发的,当点击某个div时,会顺着作用域链由内向外查找变量 i 值。 而for循环早已结束,每次找到的都是 5。
解决方法是 在闭包的帮助下,把每次循环的 i 值都封闭起来。当在事件函数中顺着作用域链查找变量 i 时,会先找到封闭在闭包环境中的 i .

for(var i = 0; i < nodes.length; i++) {
   (function(i){
         nodes[i].onclick = function () {
               alert( i )
         }
   })(i)
}

推荐阅读更多精彩内容

  • 《ijs》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 1,581评论 0 5
  • ● 闭包基础 ● 闭包作用 ● 闭包经典例子 ● 闭包应用 ● 闭包缺点 ● 参考资料 1、闭包基础 作用域和作...
    lzyuan阅读 145评论 0 0
  • js函数对象 转载文章 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解。 J...
    猩崽大叔阅读 236评论 0 0
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 6,511评论 0 38
  • 第一章: JS简介 从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数, 甚至元编程等...
    LaBaby_阅读 225评论 0 4