闭包

Apr 30, 2019 5:06·475 words ·1 minutes read

  • 闭包 和 匿名函数?
    • 闭包是指有权访问另一个函数作用域中的变量的函数
  • 要彻底理解闭包,需要知道有关如何创建作用域链以及作用域链有什么作用的细节

  • 作用域链

    • 当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。然后使用 arguments 和其他命名参数的值来初始化函数的活动对象(activation object)。但是在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,……直至作为作用域链终点的全局执行环境
  • 作用域链使得匿名函数能使用外部函数的活动对象,即使外部函数被销毁,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。

  • 闭包与变量

    • 作用域链引出了一个值得注意的副作用:它使得闭包只能取得外部函数中任何变量的最后一次改变值,中间的变化值无法记录下来
    • 如: 若我们需要一个函数数组,在数组位置 i 的函数返回 i

        function createFuntions(){
            var result = new Array();
      
            for (var i=0; i < 10; i++) {
                result[i] = function(){
                    return i;
                };
            }
      
            return result;
        }
      

      以上代码实际上,每个函数都返回 10. 因为闭包只记得外部函数变量的最后一次改变值

    • 如何实现?

        function createFuntions(){
            var result = new Array();
      
            for (var i=0; i < 10; i++) {
                result[i] = function(num) {
                    return function(){
                        return num;
                    };
                }(i);   // 直接调用函数
            }
      
            return result;
        }
      

      以上代码用 num 阻隔了外部函数的变量 i,使得 i 按值传递进 function(num) 中,function(num) 内的闭包不需要引用 createFuncitons() 的变量 i,问题也就解决了