JS引擎和他的朋友编译器和作用域的故事 第一集《var a = 2 ;》——《你不知道的js 上》读书笔记(一)

JS引擎和他的朋友编译器和作用域的故事 第一集《var a = 2 ;》

报幕

主持人:下面由我社团编译器同学、作用域同学、引擎同学为大家带来话剧表演《var a = 2 ;》。在表演前请允许他们三人做一个简单三位自我介绍。

引擎:大家好,我叫引擎,我主要负责js程序的编译和执行过程。

编译器:大家好,我是编译器,引擎的好朋友。我主要负责语法分析、代码生成等脏活累活。

作用域:我是引擎的另一位好朋友,作用域。我负责收集和维护所有的变量,并实施一套非常严格的查询规则。

三人齐:好戏正式开始!

演出正式开始

旁白:集合集合,又有人触发运行了!!

三人齐:来啦!什么任务?(三人傻眼看着新任务: var a = 2;)

引擎:分下任务啊!编译器,你负责编译,把代码生成给我,我这边和作用域打配合,当然啊,编译器那边创建变量啥的你也帮着点。

编&作:没问题!

好戏来临,各显神通

编译器:引擎大哥,我速度!我这活就是脏活累活啊!虽然说js现在被归类为解释型的语言,但他实际上也是编译语言啊,还是需要我这个编译器的!只不过它不同于其他编译型语言,一次编译就完了再执行,js是我编译一行,然后引擎执行一行,不能提前编译的啊!!尽管大体步骤也是词法分析、语法分析、代码生成,但是其实js优化部分比其他的复杂多了,因为考虑js的运行时间啊!

引擎:好了别说了,赶紧做!!

编译器:好吧,谁让我们是朋友呢!!词法分开始了,先分词吧,把var a = 2 ;分解成几个词法单元,var、a、=、2、;这五个词法单元,先放在数组里吧。接下来我要把这个转化成语法树了。看我的!这个树呢,代表了程序的结构。var a = 2 ;的抽象语法树(AST)中可能会有一个叫作 VariableDeclaration(变量声明) 的顶级节点,接下来是一个叫作 Identifier(标识),的子节点,它的值是 a, 以及一个叫作 AssignmentExpression(赋值表达式) 的子节点。AssignmentExpression 节点有一个叫作 NumericLiteral(数字文字)的子节点,它的值是 2。咦!这里有个var a变量声明啊,作用域同学在吗,查一下标识符a是否在当前的作用域 ,如果不在的话帮我在当前作用域创建一个叫做a的变量啊,处理完回个话!

作用域:我看看啊,当前作用域没有a,我给你创建一个吧!(或者当前作用域已经有了,你放心使用吧 !)

编译器:收到!上边就是语法分析,完了之后我生成一段代码,将 AST 转换为可执行代码的过程就是代码生成。这个过程与语言、目标平台等息息相关。抛开具体细节,简单来说就是有某种方法可以将 var a = 2; 的 AST 转化为一组机器指令,主要用来执行`a = 2的赋值操作。我的主要工作就这么多啦,但其实我中间还有一些其他的细小的工作哦。引擎,声明空间已经联系作用域开辟好了!你要的执行代码!给你,可以执行了!

引擎:好嘞,收到!别休息啊,马上执行完还有下一条程序给你编译!我执行下,作用域兄弟啊,当前作用域有一个叫做a的变量吗,来一个 LHS查询,因为我要给他赋值的!当然对应的还有一个RHS查询,现在不用啦,因为这个是查询值的时候用的!!

作用域:我查一下啊,我这边维护了一个作用域链,你们知道的,我这边有一套滚则来存储和查询变量,只能在当前的作用域链!回引擎,有的,编译器这哥们儿叫我创建了,就算没有我也在顶级作用域帮你创建啦,LHS查询的话如果当前查不到我就会给你创建的,但是RHS就不会哦,因为你想要值,我创建了也没有值啊!

引擎:明白,没有的话我还得再问你他的上一级作用域有没有。当前作用域有就省事啦!省的万一我找到顶级作用域也没找到,我还得抛出一个异常呢!

作用域:不会啦!我不是说了吗,如果是LHS查询的话,顶级作用域还没有的话,我会热心的当你创建一个哟,但是如果是RHS查询的话,我就不会帮你找创建,直接告诉你没有哦。 所以LHS不会抛出异常的啦

引擎:明白啦哥们儿,那我现在给他赋值了,让他的值为2!,这条语句终于执行完了!

三人齐:谢谢各位捧场!

花絮

引擎:我认为啊,这里有两个完全不同的声明,一个由编译器在编译时处理,另一个则由我在运行时处理。也就是,这段代码var a = 2应该分成两个部分,也就是 var a 和a = 2,编译器执行一个,我执行一个。但这两个都需要老作(作用域)来配合啊!
二人:可以啊!
作用域;我再解释一下RHS和LHS两个查询啊!LHS 和 RHS 的含义是“赋值操作的左侧或右侧”并不一定意味着就是“= 赋值操作符的左侧或右侧” 。赋值操作还有其他几种形式,因此在概念上最好将其理解为“赋值操作的目标是谁(LHS) ”以及“谁是赋值操作的源头(RHS) ” 。他们还有一个不同,如果已经查询到了顶级的作用域,LHS会创建的,但是RHS不会创建的!

谢幕

下集预告:

JS引擎和他的朋友编译器和作用域的故事 第二集《function foo(a) {var b=a;return a+b;}var c=foo(2);》——《你不知道的js(上卷)》读书笔记(二)

广而告之,敬请期待其他续集!

下边真的可以不看 -----

想学习一些前端的书籍吗,我都帮你整理好啦!评论打出你想读的书,给你最全的笔记干货
超级全的前端知识,面试必备、系统复习必备哟哟哟

有想法评论提出哈,欢迎交流,小编也是渣渣一枚呢~一起进步呗

这次真的可以不看 -----

点个收藏呗,要不赞一个呗,小编手都敲累了,但还是持续加更呢~

猜你喜欢

转载自blog.csdn.net/qq_36049117/article/details/107557326