你不知道的javascript上卷第一章

134 阅读3分钟

宏观编译原理

  • 词法分析(将代码块分解成相应的词法单元,即将关键字,运算符,数据分解)
  • 解析语法(将词法单元流转换成一个树形结构,即AST抽象语法树)
  • 代码生成(将AST转化成机器指令供计算机执行)

#### 编译器执行顺序

如某块级作用域中的代码块var a=3;

1.当遇到var a时,编译器会访问作用域查看是否已经存在同一个变量名称的变量在作用域中。
如果是就忽略该声明,继续编译。如果不存在就会要求作用域在当前作用域中声明一个新的变量a
2.接下来编译器会为引擎生成运行时所需要的代码,如果a=2之类的赋值操作。引擎运行时会访问作用域
查看是否存在对应的变量,存在就继续使用。不存在引擎就会继续查找该变量(是否是变量提升的原因呢?)

如果引擎最终找到了该变量的存在,就执行赋值,不存在就抛出错误

编译器执行变量声明操作,引擎执行赋值操作(顺带抛出错误)

important
引擎对变量的查询LHS(左手边left hand side)和RHS(右手边right hand side 或者理解为取到它的源值(retrieve his source value))
LHS一般是为左手边的变量进行赋值操作
RHS可以理解为非左右边的赋值操作或者是取变量值
e.g:
LHS: a=2; (将Number类型的值赋值给变量2,赋值操作就是所谓的LHS。这行语句只有一个LHS)
RHS: b=a; (将变量a的值赋值给b,查询a变量的值就是RHS。这里有一个LHS和一个RHS)

你不知道的javascript上的描述

    LHS和RHS的含义是“赋值操作的左侧或右侧”并不一定意味着这既是"="赋值操作符的左侧和右侧
    赋值操作符还有其他几种形式,因此在概念上最好理解为“赋值操作的目标是谁(LHS)以及谁是赋值操作的源头(RHS)”

有意思的是全局作用域的概念在这里得到的解释
引擎执行RHS的时候,如果在块级作用域中没找到的源的话,它会去上一级作用域查找
知道在全局作用域中没找到源才会抛出错误

而当执行LHS在块级作用域中的时候,赋值操作中的变量没有给声明(即使在顶层对象中野没找到该变量的声明)。
这时候会在顶层对象中创建该变量,并将其返回给引擎。这创建的条件是在非严格模式下,严格模式下回抛出错误。

上述的块级作用域需要结合《js高级程序设计》中对js里作用域的描述的理解

作用域拓展

js中只有函数作用域和全局作用域
我们所谓的作用域是在封闭的符号内的代码块所能执行的范围 即在()和{}内的作用范围
在es6规范中引入了块级作用域的概念
let和const
而let和const没有变量提升,但是存在能使变量在特定的作用域中被引用