javascript 闭包内部机制

在初学JavaScript函数式编程的时候,常常会出现使人出乎意料的结果,而缘由,大都是因为不理解JavaScript闭包引发的;理解JavaScript的闭包,能够从JavaScript的闭包内部机制出发。html

函数:编程

function creatFunctions() {
  var result = [];
  for (var i = 0; i < 10; i++) {
    result[i] = function () {
      return i
    };
  }
  return result;
};
console.log(creatFunctions())

结果:数组

0: function creatFunctions/result[i]()
1: function creatFunctions/result[i]()
2: function creatFunctions/result[i]()
3: function creatFunctions/result[i]()
4: function creatFunctions/result[i]()
5: function creatFunctions/result[i]()
6: function creatFunctions/result[i]()
7: function creatFunctions/result[i]()
8: function creatFunctions/result[i]()
9: function creatFunctions/result[i]()

这个函数会返回一组数组,应该每一个函数都应该返回对应的值;而出现结果的缘由就在于闭包不是当即执行的。闭包

一、闭包的概念

JavaScript高设中,闭包是指有权访问另外一个函数做用域的中的变量的函数,建立闭包的形式,就是在函数的内部建立另外一个函数。函数式编程

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();//MDN

displayName就是一个闭包。函数

二、闭包的内部机制

闭包的内部机制在于理解做用域链,函数的执行环境,变量对象和活动对象;this

函数被调用时会建立一个执行环境,在执行环境中初始化该函数的活动对象、变量对象、和做用域链。其中,做用域链是指向当前执行环境可访问的变量对象的指针,是一个由内而外的过程。以上述函数为例;spa

因为全部函数的执行环境底层都是在全局执行环境中,JavaScript在运行时,首先初始化活动对象,即函数自带的arguments、this变量;全局变量makeFunc、myFunc会绑定到变量对象上;该执行环境初始化以后会推入栈中,此后会初始化函数makeFunc的局部变量,读取局部变量'name';内部函数displayName的函数声明;值得注意的是,每一个执行环境的内部属性[[scope]] 保存当前执行环境可访问的变量对象,由内而外,即内部函数始终能够访问外部函数直到全局环境的全部变量,而外部环境是没法读取内部函数变量对象的;这是因为做用域链中定义的。指针

通常函数在执行完成后,会销毁其执行环境,只保留全局执行环境中变量;可是在闭包中,因为闭包并非当即执行,而是保存着内部函数执行须要的全部变量,包括内部变量和外部变量;在须要时再执行;函数执行完毕后;因为内部匿名函数的做用于链依然引用这个活动对象;所以活动对象仍然会保存在内存中。code

三、闭包的缺陷

闭包只是对函数内部的活动对象的保留,JavaScript中对变量只能保存一个定义;即 i 只能保存一个值,也就是上例中 i=10;闭包不是当即执行,当闭包执行时;向上搜索函数用到的全部变量,而内存中保存的是最后一次i的值;所以 i=10;

闭包会引用包含它函数的做用域,所以比普通函数占用更多的内存。

相关文章
相关标签/搜索