最近了解了下前端开发,发现目前可以使用C#、C++等语言进行Web开发,无需额外学习JavaScript,这是因为有了WebAssembly。本文将JavaScript与WebAssembly进行简单的介绍,为后续研究Blazor奠定基础。
JavaScript简介
1993年,NCSA发表了NCSA Mosaic,这是最早流行的图形接口网页浏览器。
1994年,Mosaic的主要开发人员创立了Netscape公司,目标是做世界第一的网页浏览器,迅速占据了浏览器市场。Netscape公司预见到网页需要变得动态,创始人Mark Andreessen认为HTML需要一种胶水语言,可以很容易的使用它来组装图片和插件之类的组件,且代码可以直接编写在网页标记中。
1995年,Netscape招募了Brendan Eich,他仅用了10天就把JavaScript的原型设计出来了。
随着Web的快速发展,JavaScript迅速流行起来,Web开发几乎只能通过JavaScript实现,JavaScript可谓是Web开发的官方语言。世界上的主流浏览器均支持JavaScript,它也是世界上大多数网站使用的语言。
JavaScript工作原理
JavaScript是一种脚本语言,它是弱类型的,也是动态类型的。JavaScript是单线程的,为了处理并发,JavaScript使用事件循环与回调函数。
JavaScript是一种高级的解释型语言,代码不进行预编译,只是将文本格式的代码发送给浏览器,由浏览器中的JavaScript引擎解释执行,因此它的性能是比不上编译语言的。
当访问网站时,使用HTTP协议请求JavaScript代码并将其流式传输到浏览器。JavaScript代码开始是保存在内存中的一堆字符。首先根据语言的语法解析器将这些字符解析为抽象语法树(AST),然后解释器将AST转换为可解释的字节码,编译器再把字节码转换成机器码。
JavaScript性能优化
JavaScript是一种动态类型语言,变量类型不需要预先定义,也不需要提前编译。这使得编写起来既简单又快速,但这也意味着JavaScript引擎需要做很多工作。当代码在页面上执行时,它必须解析、编译和优化代码。
JavaScript的语法太灵活导致大型项目开发困难,且性能不能满足一些场景的需要。如视频游戏、视频编辑、3D渲染或音乐制作等,这些场景需要进行大量计算并且需要高度的性能。这种性能很难从JavaScript中获得。
曾经许多公司希望通过浏览器插件模型来创建替代方案来满足创建复杂的交互式网页或应用程序。这些插件中最著名的是Adobe Flash,它在2000年代初期取得了巨大成功,以及微软的Silverlight。
插件技术在网络游戏和商业应用中非常流行,但随着移动端的发展,浏览器插件效率低下,史蒂夫乔布斯的“关于Flash的想法”,一封明确指出iPhone和iPad永远不会支持Adobe Flash的公开信,引发了插件时代的终结。
各大JavaScript引擎均进行了优化以提升Web体验,比如2008年谷歌开发的V8引擎,是使用C++编写的开源的JavaScript引擎,用在Chrome和Node.js中。为了提升性能,V8将JavaScript代码直接编译为更高效的机器码,跳过使用解释器生产字节码的过程。再加上隐藏类及内敛缓存技术,V8比其它JavaScript引擎的性能提升了10倍。但JIT无法对一些代码进行优化,V8又进行了其它改进,不断地优化性能。
WebAssembly的诞生
2015年,WebAssembly的工作开始了,来自谷歌、微软、Mozilla和苹果的工程师一起为网络创建了一个新的运行时。他们将WebAssembly描述为“适合编译到Web的新型可移植、大小和加载时间高效的格式”。
WebAssembly是一种可以在现代浏览器中运行的新型代码,它可以将C、C++、Rust等代码编译成WebAssembly模块。它的创建是为了在网络上获得更好的性能。它是一种低级二进制格式,体积小,因此加载和执行速度很快。
WebAssembly并非旨在完全替代JavaScript。实际上,应用程序使用WebAssembly来执行核心业务逻辑,通过JavaScript互操作层与浏览器API交互。可以在JavaScript代码中调用WebAssembly函数,也可以在WebAssembly模块中调用JavaScript函数。
WebAssembly是为速度而设计的。它的二进制文件比文本JavaScript文件小得多。由于它们的大小,它们的下载速度更快,这在慢速网络上尤其重要。但随着网络技术地发展,文件大小已经不是JavaScript的主要问题。
WebAssembly以二进制形式提供,解码速度更快。它是静态类型的,因此与JavaScript不同,引擎不需要在编译期间推测将使用哪些类型。大多数优化发生在源代码的编译期间,甚至在它进入浏览器之前。内存是手动管理的,就像在C和C++之类的语言中一样,因此也没有垃圾收集。所有这些都提供了更好、更可靠的性能。WASM二进制文件的执行时间仅比相同本机代码的执行慢20%。
使用WebAssembly,Web开发人员将能够选择其他语言,更多的开发人员将能够为Web编写代码。JavaScript仍将是大多数用例的最佳选择,但在需要提升性能时,可以选择使用专门的语言。UI和应用程序逻辑之类的部分可以使用JavaScript,核心功能在WebAssembly中。在优化现有JS应用程序的性能时,可以用更适合该问题的语言重写瓶颈。
WebAssembly不能直接访问任何平台API——DOM、WebGL、WebAudio等。要使用这些API,甚至要在页面上显示WebAssembly代码的输出,必须通过JavaScript。
WebAssembly的工作原理
JavaScript使用解释器,解释器启动简单且快速,但执行速度较慢。WebAssembly使用编译器,编译器启动很慢,但执行起来很快。
JavaScript源码到达浏览器后,先被解析成AST,再将AST解释成中间代码,然后提供给JavaScript引擎编译。WebAssembly不需要这些过程,因为它本身就是中间代码。
当WebAssembly模块通过HTTP加载时,必须在执行之前对其进行解码和编译。尽管WebAssembly是一种类似汇编的语言,但它仍然必须编译为底层处理器的机器代码。解码WebAssembly比解析JavaScript更简单、更快;此外,此解码/编译步骤可以跨多个线程拆分,并且整个过程在模块仍在下载时开始。这大大减少了下载应用程序代码和达到峰值执行速度所需的时间。
像C++和Rust这样的传统桌面语言也可以相对轻松地编译成WASM;AutoDesk在几个月内将其已有35年历史的C/C++代码库移植到WASM,而Google移植了Google Earth,两者都可以渲染复杂的3D场景并以接近本机的性能运行。Unity游戏引擎也可以在WASM中运行。
WASM得到了Mozilla、Microsoft、Google和Apple开发人员的支持,并且它对现代浏览器的支持正在快速发展。与大多数Web标准一样,它目前由W3C标准组织管理。
参考文献
维基百科:JavaScript
维基百科:JavaScript引擎
How JavaScript Engine Works?
What Is WebAssembly? by Colin Eberhardt
WebAssembly: How and why
How JavaScript works: Optimizing the V8 compiler for efficiency