WebAssembly 概念本文介绍了 WebAssembly 工作原理背后的概念,包括其目标、解决的问题以及在 Web 浏览器 JavaScript 引擎中如何运行。
什么是 WebAssembly?WebAssembly 是一种新型代码,可以在现代 Web 浏览器中运行,并提供新功能和性能上的重大提升。它主要不是为了手动编写,而是被设计为 C、C++、Rust 等源语言的有效编译目标。
这对 Web 平台具有重大意义——它提供了一种方法,可以在 Web 上以接近本机的速度运行用多种语言编写的代码,使以前无法在 Web 上运行的客户端应用程序能够运行。
更重要的是,您甚至无需了解如何创建 WebAssembly 代码即可利用它。WebAssembly 模块可以导入到 Web(或 Node.js)应用程序中,公开 WebAssembly 函数以供通过 JavaScript 使用。JavaScript 框架可以利用 WebAssembly 来实现巨大的性能优势和新功能,同时仍然使 Web 开发人员能够轻松使用这些功能。
WebAssembly 目标WebAssembly 正在 W3C WebAssembly 社区组 内创建为一个开放标准,其目标如下
快速、高效且可移植——WebAssembly 代码可以通过利用 常见的硬件功能,以接近本机的速度在不同的平台上执行。
可读且可调试——WebAssembly 是一种低级汇编语言,但它确实具有可供人阅读的文本格式(其规范仍在最终确定中),允许手动编写、查看和调试代码。
保持安全——WebAssembly 被指定在安全、沙箱化执行环境中运行。与其他 Web 代码一样,它将强制执行浏览器的同源策略和权限策略。
不要破坏 Web——WebAssembly 的设计使它能够与其他 Web 技术很好地配合,并保持向后兼容性。
注意:WebAssembly 也将在 Web 和 JavaScript 环境之外使用(参见 非 Web 嵌入)。
WebAssembly 如何融入 Web 平台?可以认为 Web 平台有两个部分
运行 Web 应用程序代码的虚拟机 (VM),例如为您的应用程序提供支持的 JavaScript 代码。
一组 Web API,Web 应用程序可以调用这些 API 来控制 Web 浏览器/设备功能并使事情发生 (DOM、CSSOM、WebGL、IndexedDB、Web 音频 API 等)。
历史上,VM 只能加载 JavaScript。这对我们来说一直很好,因为 JavaScript 足够强大,可以解决当今人们在 Web 上遇到的绝大多数问题。但是,当尝试将 JavaScript 用于更密集的用例(如 3D 游戏、虚拟现实和增强现实、计算机视觉、图像/视频编辑以及需要原生性能的其他领域)时,我们遇到了性能问题(参见 WebAssembly 使用案例,了解更多想法)。
此外,下载、解析和编译非常大的 JavaScript 应用程序的成本可能过高。移动和其他资源受限平台会进一步放大这些性能瓶颈。
WebAssembly 是一种与 JavaScript 不同的语言,但它不是作为替代品出现的。相反,它被设计为补充并与 JavaScript 协同工作,使 Web 开发人员能够利用两种语言的优势
JavaScript 是一种高级语言,灵活且富有表现力,足以编写 Web 应用程序。它有许多优势——它是动态类型的,不需要编译步骤,并且拥有庞大的生态系统,提供了强大的框架、库和其他工具。
WebAssembly 是一种低级汇编语言,具有紧凑的二进制格式,可以以接近本机的性能运行,并为具有低级内存模型的语言(如 C++ 和 Rust)提供编译目标,以便它们可以在 Web 上运行。(请注意,WebAssembly 具有 高级目标,即在将来支持具有垃圾回收内存模型的语言。)
随着 WebAssembly 在浏览器中出现,我们前面提到的虚拟机现在将加载和运行两种类型的代码——JavaScript 和 WebAssembly。
不同的代码类型可以根据需要相互调用——WebAssembly JavaScript API 将导出的 WebAssembly 代码包装在可以正常调用的 JavaScript 函数中,而 WebAssembly 代码可以导入和同步调用普通的 JavaScript 函数。事实上,WebAssembly 代码的基本单位称为模块,WebAssembly 模块在许多方面与 ES 模块对称。
WebAssembly 关键概念要了解 WebAssembly 如何在浏览器中运行,需要了解几个关键概念。所有这些概念都在 WebAssembly JavaScript API 中 1:1 地反映出来。
模块:表示 WebAssembly 二进制文件,该文件已由浏览器编译为可执行的机器代码。模块是无状态的,因此,类似于 Blob,可以在窗口和工作线程之间显式共享(通过 postMessage())。模块声明导入和导出,就像 ES 模块一样。
内存:一个可调整大小的 ArrayBuffer,包含 WebAssembly 的低级内存访问指令读取和写入的线性字节数组。
表:一个可调整大小的类型化数组,包含引用(例如指向函数的引用),这些引用不能以原始字节的形式存储在内存中(出于安全性和可移植性原因)。
实例:模块与其在运行时使用的所有状态配对,包括内存、表和一组导入值。实例就像一个 ES 模块,它已加载到特定全局范围内,并具有一组特定的导入项。
JavaScript API 为开发人员提供了创建模块、内存、表和实例的能力。在给定 WebAssembly 实例的情况下,JavaScript 代码可以同步调用其导出项,这些导出项作为普通的 JavaScript 函数公开。任意 JavaScript 函数也可以通过将这些 JavaScript 函数作为导入传递给 WebAssembly 实例,由 WebAssembly 代码同步调用。
由于 JavaScript 能够完全控制 WebAssembly 代码的下载、编译和运行方式,因此 JavaScript 开发人员甚至可以将 WebAssembly 视为仅用于高效生成高性能函数的 JavaScript 功能。
将来,WebAssembly 模块将 像 ES 模块一样可加载(使用