【《你不知道的JS(上卷①)》】一、作用域是什么?

一、作用域是什么?

储存和访问变量的值的能力将状态带给了程序。但是变量储存再哪里,当程序需要时如何找到它们?

一)、编译原理:

​ JS通常被称作 动态、解释型语言,但它实际上是 编译型语言。但与传统的编译语言不同,它不是提前编译的,编译结果也不能再分布式系统中进行移植。

​ 传统编译语言的编译会经历三个步骤:

  1. 分词/词法分析(Tokenizing/Lexing):

    将由字符组成的字符串分解成有意义的(对编程语言来说)代码块(词法单元,token)。

    例: var a = 2;

    ​ 会被分解为:var、a、=、2、;

    • 分词和词法分析之间是有区别的。
  2. 解析/语法分析(Parsing):

    将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树——抽象语法树(Abstract Syntax Tree,AST)。

  3. 代码生成:

    将前面生成的AST转换成一组机器指令。

JavaScript的编译过程要比上面所说的过程复杂许多。

简单地说,任何JavaScript代码片段在执行前都要进行编译(通常就在执行前)。因此,JavaScript编译器首先会对var a = 2;这段程序进行编译,然后做好执行它的准备,并且通常马上就会执行它。

二)、理解作用域:

概念介绍:

  • 引擎:

    从头到尾负责整个JavaScript程序的编译及执行过程。

  • 编译器:

    引擎的好朋友之一,负责语法分析及代码生成等脏活累活。

  • 作用域:

    引擎的另一位好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

编译过程中编译器会不断询问作用域内是否有所需变量!

引擎的查找方式:

LHS:进行赋值,例:a = 2;

RHS:取值,例:console.log(a); b = a; // 将a的值赋给b

三)、作用域嵌套:

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

例:

function foo(a) {
	console.log(a + b);
}
var b = 2;
foo(2);

在函数foo内对b进行RHS查询,当在foo作用域内无法完成时。会到上一层作用域寻找到b。

四)、异常:

要学会区分LHS与RHS。

  • ReferenceError:

    RHS或严格模式下的LHS查询失败。

  • TypeError:

    对RHS查询到的变量进行不当操作。

  • 非严格模式下,LHS查询失败(即全局作用域也无法找到该变量)时,会自动创建一个该名称的全局变量,并返还给引擎。

原文地址:https://www.cnblogs.com/enmac/p/13060663.html