JS的基本概念
作用域
作用域就是变量的可访问性和可见性
作用域分为静态作用域和动态作用域
JS是静态作用域,通过它就能够预测代码在执行过程中如何查找标识符
JS也是词法作用域,就是定义在词法阶段的作用域,是由写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变 无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定
事实上,在块级作用域之外调用变量会直接报错:Unkown word
变量提升
- var有变量提升
- let、const没有变量提升,提前访问会报错
- function函数可以先调用再定义
- 赋值给变量的函数无法提前调用
JS是怎么执行的
- 源代码通过词法分析和语法分析生成抽象语法树,同时会创建“执行上下文”,将AST生成的字节码逐行解释得到机器码。(见下图)
执行上下文(execution context 简称EC):当JS引擎解析到可执行代码片段(通常是函数调用)的时候,就会先做一些执行前的准备工作,这个准备工作就是执行上下文,也叫执行环境。
执行上下文包含变量环境和词法环境。
而执行上下文包括全局执行上下文、函数执行上下文、Eval执行上下文。
- 全局执行上下文:代码开始执行时就会创建,将他压执行栈的栈底,每个生命周期内只有一份
- 函数执行上下文: 当执行一个函数时,这个函数内的代码会被编译,生成变量环境、词法环境等,当函数执行结束的时候该执行环境从栈顶弹出
抽象语法树(abstract syntax tree,AST) 是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,之所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。 抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因此,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。 抽象语法树在很多领域有广泛的应用,比如浏览器,智能编辑器,编译器。链接:juejin.cn/post/703045…
- 字节码比实际代码要少的多,而对字节码进行编译执行的过程,这是通过JIT进行的。如果相同的代码出现2次及以上,就被V8认为成热代码,并直接把这部分当做机器码,并进行缓存,从而优化代码。