闭包

---恢复内容开始---

  • 闭包:有权访问另一个函数作用域中的变量的函数。
  • 创建方式:在一个函数内部创建另一个函数并返回。

  首先谈谈作用域和作用域链是如何创建的?先来介绍下几个概念:

执行环境:定义了变量和函数有权访问的其他数据,每个执行环境都会有一个与之关联的变量对象,环境中所有的变量和函数都保存在这个变量对象中。

全局执行环境:在Web浏览器中,全局执行环境被认为是Window对象。

每个函数都有自己的执行环境,当函数A被调用时,会创建一个执行环境及相应的作用域链。通过arguments参数和其他命名参数来初始化A的活动对象。在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位······直至作为作用域终点的全局执行环境。

作用域链本质上是一个指针列表,保存着指向变量对象的引用。内部函数的作用域链包含着外部函数的活动对象的引用,内部函数的活动对象在执行环境作用域链的前端,全局对象在执行环境的最末端。

变量对象包含:活动对象,全局对象。

每个执行环境对应着一个变量对象(AO),称为活动对象。全局环境的变量对象(GO)始终存在,称为全局对象。

活动对象在函数被调用前创建,函数执行完毕则销毁。(闭包的情况下不同)

 1 function createComparisonFunction(propertyName){
 2     return function(object1,object2){
 3         var value1=object1[propertyName];
 4         var value2=object2[propertyName];
 5         if(value1<value2){
 6             return -1;
 7         }else if(value1>value2){
 8             return 1;
 9         }else{
10             return 0;
11         }
12     }
13 }
14 var compare=createComparisonFunction("name");
15 var result=compare({name:"Nicholas"},{name:"Greg"});
16 console.log(result); //1

  在以上代码中,createComparisonFunction函数的作用域链包含1.全局对象,0.createComparisonFunction的活动对象。它的返回值是一个匿名函数,该匿名函数在其内部,它的作用域链被初始化为包含createComparisonFunction函数的活动对象和全局对象,即:匿名函数的作用域链包含 2.全局对象 1.createComparisonFunction的活动对象 0.匿名函数的活动对象。所以匿名函数可以访问它的外部函数的所有变量。(访问作用域链时从0开始查找)

  在外部函数执行完毕后,其活动对象不会被销毁,是因为匿名函数的作用域链仍然在引用这个活动对象。也就是说外部函数执行完毕后将断开与活动对象的连接,但匿名函数作为返回值被保存下来(保存在compare中),会继续与活动对象连接,所以可以访问到name值,该活动对象仍然会留在内存中,直到匿名函数被销毁。(所以经常说闭包会导致内存泄漏!!!)

通常闭包销毁的方式为:对象=null;解除引用值,垃圾回收机制会进行清除。

posted @ 2018-08-21 16:28  阿兰儿  阅读(145)  评论(0编辑  收藏  举报