# 作用域链

# 一、作用域

# 1、定义

作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。简言之作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。

# 2、 分类

  • 在ES6阶段之前,作用域分为两种

    • 全局作用域
    • 函数作用域;
  • 进行ES6之后,作用域分为

    • 全局作用域
    • 函数作用域
    • 块级作用域

# (1)、 全局作用域

在该作用域中的对象在代码的任何地方都能访问,其生命周期伴随着页面的生命周期。例如以下内容均在全局作用域中。

  • window上的属性(在浏览器中)
  • 最外层的函数
  • 最外层定义的变量
  • 未定义直接赋值的变量
  • 全局对象属性

js规定的全局对象的属性,三个值(Infinity、NaN、undefined)、九个函数(parseInt、parseFloat、decodeURI、encodeURI……)、一些构造器(Date、Array等)、四个用于当做命名空间的对象(Atomics、JSON、Math、Reflect)。

# (2)、 函数作用域

在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。在函数执行结束之后,函数内部定义的变量会被销毁。

# (3)、块级作用域

在ES6阶段,出现了块的概念,新增了块级作用域,同时新增了let、const命令。块级作用域简言之就是使用一对大括号{}包裹的一段代码,通过单独的大括号、if块、while块、for块、try/catch/finally等都会产生块级作用域。(对于let和const在块级作用域的特征可见前端百题斩【002】)

# 二、作用域链

# 1、定义

在每个执行上下文的变量环境中,都包含一个外部引用(成为outer),用来指向外部的指向上下文。当在查找一个变量的时候,如果在当前的变量环境中没有找到,js引擎会继续在outer所指向的执行上下文中查找,把这个查找的链条称为作用域链。

作用域链可以理解为一组对象列表,包含 父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数。

# 2、组成

作用域链由两部分组成,分别是[[scope]]属性和AO。

[[scope]]属性:指向父级变量对象和作用域链,也就是包含了父级的[[scope]]和AO

AO:自身活动对象,也就是该执行上下文中的变量对象。

扩展

如此 [[scope]]包含[[scope]],便自上而下形成一条 链式作用域。

# 3、查找规则

从当前的执行作用域开始查找变量; 如果在当前作用域中找不到该变量,则向上一级进行查找; 继续向上一层查找,直到最外层的全局作用域。

更加详细的解读 (opens new window)