💎 只有运行时的JavaScript
JavaScript从诞生至今,都是运行在浏览器环境或者V8环境的编程语言,由于它边解释边执行的特性,导致只有运行时,没有编译时。
❝这个表述是有争论的,可以理解为JavaScript的运行时和编译时是交织在一起的,这就是边解释边执行的含义。
❞
大多数的编程语言,需要将代码转为二进制字节码文件,然后才能被系统识别并运行,转码的过程就是编译时。所以很多编程语言都需要提供转码模块。比如Java使用虚拟机编辑成目标机器字节码,Python有Brython等多种编译器编译代码为字节码
早期,JavaScript从诞生的很长一段时间里,仅仅被用来和服务器通信的工具,随着ajax
的出现,用户可以在不刷新页面的情况下和服务端交互。再后来,Jquery
兴起,使我们可以快速进行JavaScript和dom的交互。此时,JavaScript一直都是只有运行时的状态。
💎 只有编译时的TypeScript
只有运行时的语言,最大的缺点就是代码里的错误只能在运行时抛出异常。这也就是为什么会出现TypeScript
,因为所有的ts文件先被编译成js文件,然后才会被运行在模板机器中,此时代码里的错误在编译阶段就可以抛出异常了。
不过TypeScript
仅仅拥有编译时,因为编译成js文件后就是JavaScript的势力圈了。
随着前端的框架的出现,引入了模板语法和Jsx的概念,才让JavaScript拥有了编译时,不过,这么说不严谨,因为这种编译时,是将基于前端框架的编译时:将框架模板或者Jsx编译成JavaScript代码的过程。
❝这里的模板是指基于JavaScript的解析的模板,Jsp、Thinkphp、Thymeleaf等模板是基于后端语言的模板。
❞
💎 编译时也有饭圈
编译时的概念被分为即时编译(JIT)和预编译(AOT):
- 即时编译(JIT):Just In Time,在宿主环境中边编译边执行
- 预编译(AOT):Ahead Of Time,编译完成之后在宿主环境中执行
Angular的编译器同时提供了两种编译方案,不过现在已经凉透了,再次上香!!!
第一次上香是在这篇文章里:🔥超级简单的Svelte,学不会你来打我
AOT的好处是可以拥有更短的运行时间, 大多数框架都采用了AOT编译技术,因为预编译(AOT)的特点,采用AOT编译技术的框架,可以对开发者的代码做充分的分析,从而有更大的优化空间。
总体来看,目前前端框架的AOT方案有两种:
- Jsx
- 模板语法
💎 运行时 VS 编译时,前端框架的选择
前端框架都是在编译时,完成代码的转换,在运行时完成编译结果的渲染。但是由于每个框架的策略不同,导致花在运行时和编译时的时间有所不同。
重运行时的React
React采用Jsx方案编译,由于Jsx语法过于灵活,导致在编译时,React可以做的优化有限,所以,React将很多工作放在了运行时阶段。
重编译时的SolidJS和Svelte
SolidJS也采用了Jsx做AOT编译,不过,为了可以直接编译出可执行的JavaScript代码片段,选择对Jsx的灵活的语法做了限制。比如提供Show标签代替if语法,使用For标签代替for语法等。从而让它可以在编译时完成大量的工作。
Svelte和Vue都采用了模板语法方案做AOT编译,不过Vue的模板语法是基于HTML的,而Svelte的模板语法是基于JavaScript的,这就导致了Svete可以直接编译出JavaScript代码片段,从而减少运行时的时间。
平衡大师Vue
而Vue编译之后的结果是不可运行的Vnode,在运行时,需要像React一样,解析编译结果为JavaScript代码,然后再目标环境运行代码。
🎉 总结
我根据我的理解(主观性强,参考下就行),绘制了编译时到运行时,代码成为可执行JavaScript的示意图图如下:
所以你觉得是运行时的框架好还是编译时的框架好了?
最后,希望大家理性看待这个问题,框架之间”卷“起来,对我们开发者来说是好事,
附上犹大的推特照片: