闭包、执行环境、做用域链

闭包是指有权访问另外一个函数做用域中的变量的函数,建立的常见方式就是在一个函数内部建立另外一个函数。

咱们来理解下执行环境和做用域链:
     1.执行环境有全局执行环境和函数执行环境之分。
     2.每次进入一个新的执行环境,都会建立一个用于搜索变量和函数的做用域链。
     3.函数的局部环境不只有权访问函数做用域中的变量,并且有权访问其包含(父)环境,由底向上乃至全局环境。
     4.变量的执行环境有助于肯定应该什么时候释放内存。

执行环境和做用域链
function createComparisonFunction(propertyName){
     return function(object1,object2){
     var value1=object1[propertyName];
     var value2=object2[propertyName];
     
     if(value<value2){
          return -1;
     }else if(value1>value2){
          retutn 1; 
     }else{
         return 0; 
     }
     };
}
//建立函数
var compareNames=createComparisonFunction ("name");
//调用函数
var result=compareNames({name:"joey"},{name:"ross"});
//接触对匿名函数的引用,用于释放内存
compareNames=null;
由于只是用于本身增强理解,就直接把图片放在这里了,由于用于文字实在很难描述出来做用域链的关系。
值得一提的是,每一个执行环境都有表示变量的对象--变量对象,全局环境中的变量对象始终存在,而内部函数的局部环境变量则只在函数执行过程当中存在。
而在这个例子中,createComparisonFunction()的做用域链包含两个变量对象,一个自己的活动对象,一个全局变量对象,而匿名函数的做用域链包含着三个对象变量,多了一个自身的闭包活动对象,外面访问不进来,里面却能够访问外面,因此也包含外部函数的活动对象和全局变量对象,重要的是,当外部函数执行完毕以后,它的活动对象也不会被销毁,由于匿名函数的做用域连接仍然在引用这个活动对象,换句话说,外部函数返回后,其执行环境会销毁,可是它的活动对象依然留在内存中,知道匿名函数被销毁,外部函数的活动对象才会被销毁。



闭包与变量
function create(){
     var result=new Array();
     for(var i=0; i<10, i++){
          result[i]=function(){
              return i
          }
     }
}
//蓝色的全局变量对象,红色的是create()函数活动对象,绿色的闭包的活动对象。

做用域链的这种配置机制引出一个值得注意的反作用, 闭包只能取得包含函数中任何变量的最后一个值。
上面这句话是重点,这个代码我起初没看懂的,反复理解了以后才懂,这个函数会返回一个函数数组, [0(),1().....9()],从0到9,而函数返回的 i  值应该对应函数名称,便是0()里面返回0,1()里面返回1,以此类推,实际上每一个函数返回的都是10,由于 create()这个函数的做用域链保存这这个函数的活动对象,活动对象有result,还有i,函数调用后,变量 i 的值已是10,而且保存在活动对象里,此时闭包去引用的都是同一个 i 。