几乎所有编程语言最基本的功能之一,就是能够储存变量当中的值,并且能在之后对这个 值进行访问或修改。事实上,正是这种储存和访问变量的值的能力将状态带给了程序。
尽管通常将 JavaScript 归类为“动态”或“解释执行”语言,但事实上它是一门编译语言。
总结:变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如 果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对 它赋值。
var a = 2;--> 编译器声明,引擎赋值。
作用域 引擎的另一位好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查 询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
作用域是根据名称查找变量的一套规则。
遍历嵌套作用域链的规则很简单:引擎从当前的执行作用域开始查找变量,如果找不到, 就向上一级继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找过程都 会停止。
function foo(a) {
console.log(a + b); // VM19:2 Uncaught ReferenceError: b is not defined
b = a;
}
foo(2);
相较之下,当引擎执行 LHS 查询时,如果在顶层(全局作用域)中也无法找到目标变量, 全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非 “严格模式”下。
严格模式在行为上 有很多不同。其中一个不同的行为是严格模式禁止自动或隐式地创建全局变量。
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对 变量进行赋值,那么就会使用 LHS 查询;如果目的是获取变量的值,就会使用 RHS 查询。
JavaScript 引擎首先会在代码执行前对其进行编译,在这个过程中,像 var a = 2 这样的声 明会被分解成两个独立的步骤: 1. 首先,var a 在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。 2. 接下来,a = 2 会查询(LHS 查询)变量 a 并对其进行赋值。