是什么?解决了什么问题?带来什么新的问题?
(官方解释)是一个可移植、体积小、加载快并且兼容 Web 的全新格式。
WebAssembly (Wasm)是一种在浏览器中可以执行的二进制指令(编译目标)。
意义: 加速 Web 应用
- 语法太灵活导致开发大型 Web 项目困难;
- 性能不能满足一些场景的需要。_
特点:
- 高效。有完整的语义, wasm是体积小且加载快的二进制格式,便于发挥硬件能力达到原生执行效率。
- 体积小:由于浏览器运行时只加载编译成的字节码,一样的逻辑比用字符串描述的 JS 文件体积要小很多;
- 加载快:由于文件体积小,再加上无需解释执行,WebAssembly 能更快的加载并实例化,减少运行前的等待时间;
- 安全。 运行在沙箱化的执行环境中。web环境中严格遵守同源策略以及浏览器安全策略。
- 开放。 有一套规整的文本格式用来调试、测试、实验、优化、编写。
- 标准。在web中被设计乘无版本、特性可测试、向后兼容。可被JS调用, 调用功能,进入JS上下文。可运行在浏览器下, 也可在非web环境下。
- 兼容性问题少:WebAssembly 是非常底层的字节码规范,制订好后很少变动,就算以后发生变化,也只需在从高级语言编译成字节码过程中做兼容。可能出现兼容性问题的地方在于 JS 和 WebAssembly 桥接的 JS 接口。
使用场景:游戏、CAD应用、图像/视频编辑(类似桌面应用)
基础使用?注意事项?
WebAssembly 模块定义的一些功能可以通过 JavaScript 来调用。所以就像你通过 npm 下载 lodash 模块并通过 API 使用它一样
WebAssembly 模块的组成部分
必须部分:
- Type。在模块中定义的函数的函数声明和所有引入函数的函数声明。
- Function。给出模块中每个函数一个索引。
- Code。模块中每个函数的实际函数体。
可选部分:
- Export。使函数、内存、表(tables)、全局变量等对其他 WebAssembly 或 JavaScript 可见,允许动态链接一些分开编译的组件,即 .dll 的WebAssembly 版本。
- Import。允许从其他 WebAssembly 或者 JavaScript 中导入指定的函数、内存、表或者全局变量。
- Start。当 WebAssembly 模块加载进来的时候,可以自动运行的函数(类似于 main 函数)。
- Global。声明模块的全局变量。
- Memory。定义模块用到的内存。
- Table。使得可以映射到 WebAssembly 模块以外的值,如映射到 JavaScript 的对象。这在间接函数调用时很有用。
- Data。初始化导入的或者局部内存。
- Element。初始化导入的或者局部的表。
原理?
每一种目标汇编语言(x86、ARM)都依赖于特定的机器结构。而 WebAssembly 与其他的汇编语言不一样,它不依赖于具体的物理机器。可以抽象地理解成它是概念机器的机器语言,而不是实际的物理机器的机器语言。WebAssembly 指令有时也被称为虚拟指令。它比 JavaScript 代码更直接地映射到机器码,它也代表了“如何能在通用的硬件上更有效地执行代码”的一种理念。
编译到 .wasm 文件: 对于 WebAssembly 支持情况最好的编译器工具链是 LLVM
代码是如何工作的:基于栈的虚拟机
加需要两个值,所以它从堆栈顶部取两个值就可以了。那么加指令就可以变的更短(单字节),因为指令不需要指定源寄存器和目的寄存器。这也使得 .wasm 文件变得更小,进而使得加载 .wasm 文件更快。
WebAssembly 比 JavaScript 执行更快是因为:
- 文件抓取阶段,WebAssembly 比 JavaScript 抓取文件更快。即使 JavaScript 进行了压缩,WebAssembly 文件的体积也比 JavaScript 更小;
- 解析阶段,WebAssembly 的解码时间比 JavaScript 的解析时间更短;
- 编译和优化阶段,WebAssembly 更具优势,因为 WebAssembly 的代码更接近机器码,而 JavaScript 要先通过服务器端进行代码优化。
- 重优化阶段,WebAssembly 不会发生重优化现象。而 JS 引擎的优化假设则可能会发生“抛弃优化代码<->重优化”现象。
- 执行阶段,WebAssembly 更快是因为开发人员不需要懂太多的编译器技巧,而这在 JavaScript 中是需要的。WebAssembly 代码也更适合生成机器执行效率更高的指令。
- 垃圾回收阶段,WebAssembly 垃圾回收都是手动控制的,效率比自动回收更高。