JAVASCRIPT
VUE
REACT
NODE
ES6
TYPESCRIPT

关于js闭包

2017. 05. 10    

关于闭包做一个小的总结

JavaScript采用词法作用域,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性叫‘闭包’。《JavaScript权威指南》

闭包是指有权访问另一个函数作用域中的变量的函数。《JavaScript高级程序设(第3版)》

显而易见,从这两本书中的概念可以看出,理解函数作用域对理解闭包至关重要,而作用域涉及到的变量提升、局部变量、全局变量、执行环境、执行栈、调用栈。

var scope = "global scope";
function checkscope(){
  var scope = "local scope";
  function f(){return scope}
  return f()
}
checkscope() //local scope
var scope = "global scope";
function checkscope(){
  var scope = "local scope";
  function f(){return scope}
  return f;
}
checkscope()() //local scope

执行环境是 JavaScript 中最为重要的一个概念。执行环境定义了变量或函数有权问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存这个对象中。 全局执行环境是最外围的一个执行环境。根据 ECMAScript 实现所在的宿主环境不同,表示执行环境的对象也不一样。在 Web 浏览器中,全执行环境被认为是 window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的。某个执行环境中的有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出——例如关闭网页或浏览器——时才会被销毁)。 每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控权返回给之前的执行环境。ECMAScript 程序中的执行流正是由这个方便的机制控制着。 当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activationobject)作为变量对象。活动对象在最开始时只包含一个变量,即 arguments 对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。