至于这篇文章的标题,我不认为参与写这篇文章或阅读这篇文章的人是白痴。但有时候一个话题让你觉得自己像个白痴,JavaScript引擎就是其中一个话题,至少对我来说是这样。
有时候写Web应用的代码会觉得充满了魔力,因为我们只写一系列的字符,然后就可以在浏览器中看到效果了。但是了解魔术背后的技术可以帮助你提高编程技能。至少当你试图解释JavaScript驱动的web或移动应用程序的幕后发生了什么时,你会觉得不那么愚蠢。
很多年前,当我还是一名研究生讲师的时候,我向一位教授抱怨说,我没有掌握法语的语法点,这些语法点特别难懂,可以教给我的本科生。我记得她当时说的话:“有时候,学东西的唯一方法就是教。”
尝试通过JavaScript引擎向工程师解释NativeScript是如何在幕后工作的,并在运行时调用native APIs——。面对如此复杂的工作,很容易迷失在杂草中。事实上,任何JavaScript开发人员都应该对我们每天使用的基于这项技术的引擎感到好奇。现在让我们仔细分析一下JavaScript引擎都做了什么,为什么不同的平台使用不同的引擎,这些年它们是如何发展的,作为开发人员为什么要关注这些。
首先,一些专业术语。
“JavaScript引擎”通常被称为虚拟机。“虚拟机”是指由软件驱动的给定计算机系统的模拟器。虚拟机有很多种类型,根据它们模拟或替换真实物理机的准确程度进行分类。
例如,“系统虚拟机”提供了一个完整的可以运行操作系统的仿真平台。苹果用户熟悉的Parallels是一个虚拟机,可以让你在苹果上运行Windows。
另一方面,“进程虚拟机”并不具备所有功能,可以运行程序或进程。Wine是一个进程虚拟机,允许你在Linux上运行Windows应用,但是它并没有在Linux上提供完整的Windows操作系统。
JavaScript虚拟机是一种进程虚拟机,专门设计用于解释和执行JavaScript代码。
注意:区分在浏览器中布局页面布局的布局引擎和解释并执行代码的底层JavaScript引擎是非常重要的。这里可以找到一个很好的解释。
那么,确切地说,JavaScript引擎是什么,它是做什么的?
JavaScript引擎的基本工作是将开发人员编写的JavaScript代码转化为高效、优化的代码,使其能够被浏览器解释,甚至嵌入到应用程序中。事实上,JavaScriptCore自称“优化虚拟机”。
更准确地说,每个JavaScript引擎都实现了ECMAScript的一个版本,而JavaScript是它的一个分支。随着ECMAScript的发展,JavaScript引擎得到了改进。之所以有这么多不同的引擎,是因为它们都被设计成在不同的网络浏览器、无头浏览器或运行时环境(如Node.js)中运行
也许你对网页浏览器比较熟悉,但是什么是无头浏览器呢?它是一个没有图形用户界面的网络浏览器。它们对于web产品的自动化测试非常有用。一个很好的例子是PhantomJS。Node.js和JavaScript引擎有什么关系?Node.js是一个异步和事件驱动的框架,它允许您在服务器端使用JavaScript。既然是驱动JavaScript的工具,那么也是由JavaScript引擎驱动的。
根据上面对虚拟机的定义,很容易理解JavaScript引擎之所以被称为进程虚拟机,是因为它唯一的目的就是读取和编译JavaScript代码。这并不意味着它只是一个简单的引擎。例如,JavaScriptCore有六个“构建块”,可以分析、解释、优化和垃圾收集JavaScript代码。
它是如何工作的?
当然,这取决于发动机。吸引我们注意力的两个主要引擎是NativeScript,分别是WebKit的JavaScriptCore和谷歌的V8引擎。这两个引擎以不同的方式处理代码。
JavaScriptCore执行一系列步骤来解释和优化脚本:
词法分析是指将源代码分解成一系列含义明确的符号或字符串。然后用解析器分析这些符号,并将它们构建成语法树。然后四个JIT(准时制)进程开始参与解析和执行解析器生成的字节码。什么事?简单来说,JavaScript引擎会加载您的源代码,将其分解为字符串(也称为分词),然后将这些字符串转换为编译器可以理解的字节码,然后执行这些字节码。
谷歌V8引擎是用c写的,它还可以编译执行JavaScript源代码,处理内存分配和垃圾收集。它设计由两个编译器组成,可以直接将源代码编译成机器码:
Full-codegen:输出未优化代码的快速编译器曲轴:是一个以高执行效率输出优化代码的慢速编译器。如果曲轴确定要优化的代码是全代码生成的未优化代码,它将替换全代码生成。这个过程被称为“曲轴加工”。
一旦机器代码在编译过程中生成,引擎将向浏览器公开ECMA标准中指定的所有数据类型、运算符、对象、函数,或者任何需要在运行时使用的东西,就像NativeScript一样。
有哪些JavaScript引擎?
有很多令人眼花缭乱的JavaScript引擎可以用来解释、分析和执行您的客户端代码。每个浏览器版本发布后,其JavaScript引擎可能会发生变化或优化,以跟上JavaScript代码执行技术的变化。
在你被这些浏览器引擎的名字完全搞混之前,请记住,这些引擎和基于它们的浏览器已经加入了许多营销元素。在这篇对JavaScript编译非常有用的分析中,作者讽刺地指出:“你不知道的是,大约37%的编译器是由营销组成的,这是你能做的为数不多的重塑编译器品牌的事情之一。因此,智能营销有一系列名称:SquirrelFish、Nitro、SFX……"。
在牢记营销对命名和重命名这些引擎的影响的同时,注意JavaScript引擎发展历史上的几个重要事件是很有用的。我做了一个图表让你明白:
浏览器、无头浏览器或运行时JavaScript引擎Mozilla spider monkey Chrome V8 Safari JavaScript core IE和Edge Chakra PhantomJS JavaScript core html unit Rhino trifleejs v 8 node . js v8io . js * V8 * JavaScript core已被重写为SquirrelFish,升级版本为QuirrelFish Extreme,也称为Nitro。然而,构成Webkit实现基础的JavaScript引擎是JavaScriptCore(比如Safari)。
**iOS开发者应该知道,移动设备上的Safari使用Nitro,但UIWebView不包含JIT编译,所以体验会比较慢。但是开发者可以在iOS8中使用带有Nitro的WKWebView,体验明显更快。混合移动应用的开发者应该松一口气。
io.js与Node.js分离的原因之一是为了支持V8版本的引擎。正如这里所描述的,这仍然是一个挑战。
为什么要关注?
JavaScript引擎的代码解析和执行过程的目标是在最短的时间内编译优化后的代码。
最重要的是,这些引擎的演进与我们对web和移动平台发展的不断探索息息相关,让它们能够拥有尽可能高的性能,相辅相成。为了跟踪这种演变,您可以在基准图中看到各种引擎的行为,如arewefastyet.com所总结的那样。例如,比较Chrome与V8发动机和非曲轴发动机的性能是很有趣的。
任何web开发人员都应该意识到,我们试图编写、调试和维护的代码在不同的浏览器中会有不同的执行效果。为什么一段代码在一个浏览器上运行得很慢,而在另一个浏览器上却快得多?
同样,移动开发人员,尤其是那些使用webview显示页面内容的开发人员,或者那些使用像NativeScript这样的运行时环境的开发人员,希望知道是什么引擎在解释和执行他们的JavaScript代码。移动网络开发者应该注意浏览器在小设备上的局限性和可能性。作为一个想要持续发展的web、移动或者应用开发者,时刻关注JavaScript引擎的变化会给你带来很大的回报。
总结:
js中的基本数据类型是未定义的null布尔值String,js中的复杂数据类型,是所有对象的基本类型。js和其他语言一样,有9个基本的控制语句。JS中的函数不需要指定返回值。实际上,没有指定返回值的函数会返回undefinedjs中的参数,这些参数可以随意传递。注意arguments[]数组。它可以帮助你,js中的函数不能重载,但是你可以模仿它们。