导出的 WebAssembly 函数
导出的 WebAssembly 函数是在 JavaScript 中表示 WebAssembly 函数的方式。本文将更详细地介绍它们。
导出的… 什么?
导出的 WebAssembly 函数基本上就是 JavaScript 的包装器,用于在 JavaScript 中表示 WebAssembly 函数。当你调用它们时,后台会进行一些活动,将参数转换为 Wasm 可以处理的类型(例如将 JavaScript 数字转换为 Int32),然后将参数传递给 Wasm 模块内的函数,调用该函数,并将结果转换回 JavaScript。
您可以通过两种方式检索导出的 WebAssembly 函数
- 通过调用现有表的
Table.prototype.get()
。 - 通过访问通过
Instance.exports
从 Wasm 模块实例导出的函数。
无论哪种方式,您都会为底层函数获得相同类型的包装器。从 JavaScript 的角度来看,就好像每个 Wasm 函数也*是*一个 JavaScript 函数一样——但它们被封装在导出的 Wasm 函数对象实例中,并且访问它们的途径有限。
一个例子
让我们看一个例子来澄清一下(您可以在 GitHub 上找到此示例,网址为 table-set.html;您也可以 在线查看,并查看 Wasm 的 文本表示)
const otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
WebAssembly.instantiateStreaming(fetch("table.wasm")).then((obj) => {
const tbl = obj.instance.exports.tbl;
console.log(tbl.get(0)()); // 13
console.log(tbl.get(1)()); // 42
otherTable.set(0, tbl.get(0));
otherTable.set(1, tbl.get(1));
console.log(otherTable.get(0)());
console.log(otherTable.get(1)());
});
在这里,我们使用 WebAssembly.Table
构造函数从 JavaScript 创建一个表(otherTable
),然后我们使用 WebAssembly.instantiateStreaming()
方法将 table.wasm
加载到我们的页面中。
然后,我们获取从模块导出的函数,通过 tbl.get()
检索它们引用的函数,并将调用每个函数的返回值记录到控制台。接下来,我们使用 set()
来使 otherTable
表包含与 tbl
表相同的函数引用。
为了证明这一点,我们然后从 otherTable
中检索这些引用并将其结果打印到控制台,结果相同。
它们是真正的函数
在前面的示例中,每次调用 Table.prototype.get()
的返回值都是一个导出的 WebAssembly 函数——这正是我们一直在讨论的。
值得注意的是,它们是真正的 JavaScript 函数,同时也是 WebAssembly 函数的包装器。如果您在 支持 WebAssembly 的浏览器中加载上述示例,并在控制台中运行以下行
const testFunc = otherTable.get(0);
typeof testFunc;
您将获得返回值 function
。然后,您可以像处理 JavaScript 中的其他 函数一样,对该函数执行几乎任何操作—— call()
、bind()
等等。testFunc.toString()
会返回一个有趣的结果
function 0() { [native code] }
这让您对它的包装器性质有了更深入的了解。
关于导出的 WebAssembly 函数,还有一些其他注意事项