作用域

作用域是根据名称查找变量的一套规则

作用域无法通过 JavaScript 代码访问,它存在于 JavaScript 引擎内部。

作用域的两种工作模型

  • 词法作用域

    • 词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则
    • 特征:词法作用域的定义过程发生在代码的书写阶段
  • 动态作用域

    • 动态作用域并不关心函数和作用域是如何声明以及在何处声明,只关心它们从何处调用

    • 作用域链是基于调用栈的,而不是代码中的作用域嵌套

    • 特征:动态作用域是在运行时确定的。

JavaScript并不具有动态作用域,它只是词法作用域,但是this机制某种程度上很像动态作用域。

作用域嵌套

在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层作用域(也就是全局作用域)为止。

作用域查找会在找到第一个匹配的标识符时停止。

在多层嵌套作用域中可以定义同名的标识符,这叫做“遮蔽效应”(内部的标识符遮蔽了外部的标识符)

1function foo() {
2  let name = '小帅';
3  function bar(){
4    let name = "小美"
5    function test(){
6      console.log(name);
7    }
8    test()
9  }
10  bar()
11}
12foo()

作用域查找始终从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见第一个匹配的标识符为止。

全局变量会自动成为全局对象(window)的属性,因此可以不直接通过全局对象的词法名称,而是间接地通过全局对象属性的引用来对其进行访问

1window.name

变量的赋值操作会执行两个动作

  • 首先,编译器会在当前作用域中声明一个变量(如果之前没有声明过);

  • 在运行时,引擎会在作用域中查找该变量,如果能够找到就会对它赋值。