原文链接: WebAssembly 简单介绍
上一篇: js 立即执行函数 IIFE
下一篇: js WebAssembly fib 效率对比 python java c/c++
参考
https://segmentfault.com/a/1190000008402872?_ea=1932144
WebAssembly入门
本文不讨论 WebAssembly 的发展,只是一步一步地教你怎么写 WebAssembly 的各种 demo。文中给出的例子我都放在 GitHub 中了( 仓库地址 ),包含了编译脚本和编译好的可执行文件,只需再有一个支持 WebAssembly 的浏览器就可以直接运行。
配置开发调试环境
安装编译工具
略。 参考官方 Developer’s Guide 和 Advanced Tools ,需要安装的工具有:
-
Emscripten
-
Binaryen
-
WABT (WebAssembly Binary Toolkit)
安装过程挺繁琐的,得本地 clone 代码再编译。
安装浏览器
作为一个新技术,之所以说 WebAssembly 前途明媚,不仅是因为 W3C 成立了专门的 Webassembly Community Group ,被标准认可;也是因为这次各大主流浏览器厂商(难得的)达成了一致,共同参与规范的讨论,在自家的浏览器里都实现了。
体验新技术,建议使用激进版浏览器,最新版本中都已经支持了 WebAssembly。
-
黄色的 Chrome ( Chrome Canary )
-
紫色的 Safari ( Safari Technology Preview )
-
深蓝色的 Firefox ( Firefox Nightly )
-
改头换面的 IE ( Microsoft Edge )
除了上边几个激进的浏览器,在主流版本里开启 flag 也是可以使用 WebAssembly 的:
-
Chrome: 打开
chrome://flags/#enable-webassembly
,选择enable
。 -
Firefox: 打开
about:config
将javascript.options.wasm
设置为true
。
快速体验 WebAssembly
想快速体验 WebAssembly ?最简单的办法就是找个支持 WebAssembly 的浏览器,打开控制台,把下列代码粘贴进去。
WebAssembly.compile(new Uint8Array(`
00 61 73 6d 01 00 00 00 01 0c 02 60 02 7f 7f 01
7f 60 01 7f 01 7f 03 03 02 00 01 07 10 02 03 61
64 64 00 00 06 73 71 75 61 72 65 00 01 0a 13 02
08 00 20 00 20 01 6a 0f 0b 08 00 20 00 20 00 6c
0f 0b`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16))
)).then(module => {
const instance = new WebAssembly.Instance(module)
const { add, square } = instance.exports
console.log('2 + 4 =', add(2, 4))
console.log('3^2 =', square(3))
console.log('(2 + 5)^2 =', square(add(2 + 5)))
})
里边这一坨奇怪的数字,就是 WebAssembly 的二进制源码。
运行结果
如果报错,说明你的浏览器不支持 WebAssembly ;如果没报错,代码的运行结果如下(还会返回一个 Promise):
2 + 4 = 6
3^2 = 9
(2 + 5)^2 = 49
其中 add
和 square
虽然做的事情很简单,就是计算加法和平方,但那毕竟是由 WebAssembly 编译出来的接口,是硬生生地用二进制写出来的!
解释代码
上边的二进制源码一行 16 个数,有 4 行零两个,一共有 66 个数;每个数都是 8 位无符号十六进制整数,一共占 66 Byte。
WebAssembly 提供了 JS API ,其中 WebAssembly.compile
可以用来编译 wasm 的二进制源码,它接受 BufferSource 格式的参数,返回一个 Promise。
那些代码里的前几行,目的就是把字符串转成 ArrayBuffer。先将字符串分割成普通数组,然后将普通数组转成 8 位无符号整数的数组;里的数字是十六进制的,所有用了 parseInt(str, 16)
。
new Uint8Array(
`...`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16))
)
如果浏览器支持通过