首页 > 应用开发 > Javascript > JavaScript深度理解——作用域
JavaScript是一门编译语言,而并不是通常所说的“动态”或“解释执行语言”。它不是提前编译的,编译结果也不能在分布式系统中进行移植。
编译语言执行之前的三个步骤:
将由字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元。示例:var a = 3; 在这个过程中会分解成下面这些词法单元: var、a、=、3、; 。
将词法单元流(数组)转换成一个由元素逐渐嵌套所组成的代表了程序语法结构的树。这个树被称为“抽象语法树”(AST)。
将抽象语法树(AST)转化成可执行代码的过程。
JavaScript引擎不止上面的三个步骤,它的步骤要复杂得多。
引擎: 从头到尾负责整个JavaScript程序的编译以及执行过程。
编译器: 负责语法分析以及代码生成。
作用域: 收集并维护由所有的标识符(及变量)组成的一系列查询,并实施一套严格的规则,确定当前执行的代码对这些变量的访问权限。
编译器在当前作用域中声明该变量(如果之前没有声明过)。
运行时引擎会在作用域中查找该变量,如果找到就对它进行赋值操作。
LHS: 变量出现在赋值操作的左侧执行LHS查询。(找到目标变量)
RHS: 变量出现在赋值操作的右侧执行RHS查询。(取到它的源值)
当一个块或函数在另一个块或函数中,就发生了作用域的嵌套。
当在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量或者抵达最外层的作用域(全局作用域)。
如果RHS查询在所有的嵌套作用域中都找不到所需的变量,引擎就会抛出
ReferenceError异常。
如果LHS查询在所有的嵌套作用域中都找不到所需的变量,则会在全局作用域中创建一个具有该名称的变量,并将其返回给引擎。(程序在非严格模式下)。
如果RHS查询找到了一个变量,但是你对其进行不合理的操作,比如:对一个非函数类型的值进行函数调用;引用null或undefined类型中的属性,引擎会抛出
TypeError的异常。
作用域的工作模型:词法作用域和动态作用域(少数编程语言使用)。
词法作用域是由你在写代码时将变量和块作用域写在哪里决定的。因此词法分析器在处理代码时会保持作用域不变。也就是我们在JavaScript中所说的作用域。
作用域查找会在找到第一个匹配的标识符时停止。在多层的嵌套作用域中可以定义同名的标识符(遮蔽效应)。
注意:
无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数声明时所处的位置决定。
词法作用域只会查找一级标识符。
eval(…)函数可以接受一个字符串作用参数,并将其中内容好像在书写代码时就存在于程序中的这个位置。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69986098/viewspace-2729329/ ,如需转载,请注明出处,否则将追究法律责任。