几乎每一种编程语言,它最基本的能力都是能够存储变量当中的值、并且允许我们对这个变量的值进 能够存储变量当中的值、并且允许我们对这个变量的值进 行访问和修改 行访问和修改。那么有了变量之后,应该把它放在那里、我们应该如何找到它们?这是不是需要我们提前约定好一套存 储变量、访问变量的规则?这套规则,就是我们常说的作用域 作用域。更多时候,我们提到作用域的时候,指的是这个规 则约束下的一个变量、函数、标识符可以被访问的区域(这时它就更具体了)

    1. var name = "张三";

    在我们看来,这只是一个声明语句。但是在 JS 引擎眼里,它却包含了两个声明:

    • var name (编译时处理)
    • name = ‘xiuyan’ (运行时处理)

    事实上,JS 也是有编译阶段的,它和传统语言的区别在于,JS 不会早早地把编译工作做完,而是一边编译一边执
    行。简单来说,所有的 JS 代码片段在执行之前都会被编译,只是这个编译的过程非常短暂(可能就只有几微妙),紧接着这段代码就会被执行。

    共有两个阶段

    • 编译阶段:编译器会找遍当前作用域,看看是不是已经有一个叫 name 的变量。如果有,那么就忽略 var name 这个声明,继续编译下去;如果没有,则在当前作用域里新增一个 name。然后,编译器会为引擎生成运行时所需要的代码,程序就进入了执行阶段
    • 执行阶段: JS 引擎在执行代码的时候,仍然会找遍当前作用 域,看看是不是有一个叫 name 的变量。如果能找到,那么好,我来给你赋值。如果找不到,它也不会放弃,它会从当前作用域里 “探出头去”,看看 “外面” 有没有,或者 “外面的外面” 有没有。如果最终仍然找不 到 name 变量,引擎就会抛出一个异常。

    是我们引擎的查找过程 查找过程 —— 探出头去—- 探出头去?—->“外面外面” ?这就引出了我们 JS 作用域里一个非常重要的概念 —— 作用域链。 作用域套作用域,就有了作用域链

    作用域本质上就是程序存储和访问变量的规则 存储和访问变量的规则。