js基础之作用域链与闭包,执行上下文与活动对象
什么是执行上下文(或叫执行环境: Execution context, EC)?
- 执行环境定义了变量或函数有权访问的其他数据,每个函数都有自己的执行环境。通俗来讲,就是执行JS代码的环境的抽象概念。执行环境分为三类:
全局执行环境——浏览器环境下是window
局部执行环境——函数被调用时被创建
eval执行环境——不建议使用该方法 - JS在执行代码时会将代码运行时创建的所有执行上下文压入一个栈内,即执行环境栈。
当 JavaScript 引擎第一次执行JS代码时,它会创建一个全局的执行上下文并且压入当前执行环境栈。每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。
e.g.:
1 | function A() { |
上面的代码刚开始执行环境栈里只有全局执行环境,随后执行A方法,即创建A的执行环境并将其压入执行环境栈,接着是B,B方法执行完后立即释放。最后只剩下全局执行环境

什么是变量对象?
- 每个执行环境中都包含一个变量对象,环境中定义的所有变量和函数都保存在这个对象中,包括argumnets、variables、functions
什么是作用域链(scope chain)?
- javascript函数的执行用到了作用域链,这个作用域链是函数定义的时候创建的,当定义一个函数时,它实际保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的作用域链。作用域链的前端始终都是当前执行的代码所在环境的变量对象。作用域链的末端始终都是全局执行环境的变量对象。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有权访问。在执行环境中,用[[scope]]来表示。
e.g.:
1 | function A() { |
如上例,执行到A内部的B方法时,B()的变量对象内没有valA变量,即沿着作用域链向上查找,找到A的变量对象里有valA,即输出valA的值
什么是闭包?
闭包就是一个函数可以访问另一个函数作用域内的变量,一般容易出现在函数内部创建新的函数
调试工具
使用chrome的Scope可以看到当前的作用域链和执行上下文
call stack是执行环境栈