闭包问题详解

一.闭包

特点:
    • 让外部访问函数内部变量成为可能;
    • 局部变量会常驻在内存中;
    • 可以避免使用全局变量,防止全局变量污染;
缺点:
    • 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
应用场景 
    • 实现变量的私有化
    • 节流防抖函数等
 
  网上有很多的说法,先不与考虑。官方说法:函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域JavaScript,函数在每次创建时生成闭包。
 
  这边查阅相关资料之后,发现闭包的理解,应该结合执行环境及作用域来分析。首先,我们应当知道,当函数被调用时,会创建一个执行环境(execution context)及相应的作用域链(ps:作用域链本质上是一个指向变量对象的指针列表)。而每个执行环境都有一个 与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。
  即,当函数调用时会创建执行环境,作用域链,初始化变量对象
 
  正常情况下,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。 而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
  即,当函数调用完毕,执行环境出栈,作用域链会销毁,而与之关联的变量对象也会销毁。
 
OK,知道以上知识了,我们来看个
 
简单例子1
 function A(){
    var age = 10;
    return function(){
      return age;
    }
  }
  var  b = A();
  b(); 
  当A调用完毕后,按照正常情况,函数执行完毕,变量对象会被销毁。
  但是这个例子中,匿名函数引用了A函数中的 age变量,即当A函数执行完毕,因为A函数的变量对象被匿名函数所引用,JS的垃圾回收是引用计数机制。所以A函数的变量对象不会被销毁。只有当匿名函数销毁时,没有了对A函数的变量对象的引用时,A函数的变量对象才会被销毁。
   
 
简单例子2
  
function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i; 
        };
    }
    return result;
}
//result: 10 10 10 ...

function createFunctions(){
var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(num){
            return function(){
      return num;
    }
        }(i);    
   return result;
 }
}     
//return:1 2 3 ...           

 

 这个例子,也是闭包的典型例子,不过它主要是因为函数参数的值传递。由于函数参数是按值传递的,所以就会将变量 i 的当前值复制给参数 num。而在这个 匿名函数内部,又创建并返回了一个访问 num 的闭包。这样一来,result 数组中的每个函数都有自己 num 变量的一个副本,因此就可以返回各自不同的数值了。



  
  
 
 
 

posted @ 2020-05-31 12:31  小L同学  阅读(204)  评论(0编辑  收藏  举报