blob: c19706f59433a1c197366b708b4e3c90224191ff (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
---
title: 导出的WebAssembly函数
slug: WebAssembly/Exported_functions
tags:
- JavaScript
- WebAssembly
- wasm
- 导出
- 导出的wasm函数
- 导出的函数
- 指南
translation_of: WebAssembly/Exported_functions
---
<div>{{WebAssemblySidebar}}</div>
<p class="summary">导出WebAssembly函数的过程,其实就是指这些函数在JavaScript中如何用表示。本文更详细的介绍它们。</p>
<h2 id="导出的...什么?">导出的...什么?</h2>
<p>导出的WebAssembly函数只是用JavaScript来表示WebAssembly函数的封装而已。当你调用它们的时候,就会有一些后台活动把参数转换为wasm能够处理的类型(例如,把JavaScript数字转换为Int32类型),参数被传递到wasm模块中的函数,函数被调用,返回值被转换并传回到JavaScript。</p>
<p>你可以通过两种方式来获得导出的WebAssembly函数:</p>
<ul>
<li>在一个已经存在的表格上调用<a href="https://developer.mozilla.org/en-US/docs/WebAssembly/API/Table/get">Table.prototype.get()</a>。</li>
<li>通过<a href="https://developer.mozilla.org/en-US/docs/WebAssembly/API/Instance/exports">Instance.exports</a>从一个wasm模块实例获取导出的函数。</li>
</ul>
<p>无论哪种方式,你得到的都是底层函数的相同封装。从JavaScript的角度来看,每一个wasm函数看起来也是一个JavaScript函数——但是,它们被封装在导出的wasm函数对象实例中,并且只有有限的方式来获取它们。</p>
<h2 id="一个例子">一个例子</h2>
<p>让我们看个例子从而让事情更清晰(你可以在GitHub上找到这个例子<a href="https://github.com/mdn/webassembly-examples/blob/master/other-examples/table-set.html">table-set.html</a>;或者<a href="https://mdn.github.io/webassembly-examples/other-examples/table-set.html">实时运行</a>然后查看wasm<a href="https://github.com/mdn/webassembly-examples/blob/master/text-format-examples/table.wat">文本表示</a>):</p>
<pre class="brush: js">var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
fetchAndInstantiate('table.wasm').then(function(instance) {
var tbl = 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)());
});</pre>
<p>在这里,我们使用<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table">WebAssembly.Table</a>构造函数在JavaScript中创建了一个表格(otherTable),然后使用<a href="https://github.com/mdn/webassembly-examples/blob/master/wasm-utils.js">fetchAndInstantiate()</a>实用函数把table.wasm加载到我们的页面。</p>
<p>然后,我们得到了从模块中导出的函数,通过<a href="https://developer.mozilla.org/en-US/docs/WebAssembly/API/Table/get">tbl.get()</a>获取引用的函数并且把每一次的调用结果输出到控制台。接下来,我们使用set()使得otherTable表格包含了与tbl表格相同的函数。</p>
<p>为了证明这一点,我们从otherTable 中获取了这些引用并且也把他们的结果打印到控制台,结果是一样的。</p>
<h2 id="它们确实是函数">它们确实是函数</h2>
<p>在前面的例子中,每次<a href="https://developer.mozilla.org/en-US/docs/WebAssembly/API/Table/get">Table.prototype.get()</a>调用的返回值都是一个导出的WebAssembly函数——这正是我们一直在讨论的。</p>
<p>它们确实是JavaScript函数也是对WebAssembly函数的封装。如果你把上面的例子加载到<a href="https://developer.mozilla.org/en-US/docs/WebAssembly#Browser_compatibility">支持WebAssembly的浏览器</a>中,然后在你的控制台运行下面几行代码:</p>
<pre class="brush: js">var testFunc = otherTable.get(0);
typeof testFunc;</pre>
<p>你得到的返回结果是function 。对于这个函数,你可以像对待其他JavaScript<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function">函数</a>那样做你想做的任何事——<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a>、 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind()</a>等等。testFunc.toString()返回一个有趣的结果:</p>
<pre class="brush: js">function 0() {
[native code]
}</pre>
<p>这带给你关于封装类型特征的更多理解。</p>
<p>关于导出的WebAssembly函数的一些其他值得关注的特性:</p>
<ul>
<li>它们的<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length">length</a>属性是在wasm函数签名中声明的参数的数量。</li>
<li>它们的<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name">name</a>属性是函数在wasm模块中的索引调用toString()的返回值。</li>
<li>如果你尝试调用一个接受或返回一个i64类型值的导出的wasm函数,目前它会抛出一个错误,因为JavaScript当前没有精确的方式来表示一个i64。不过,这在将来可能会改变——在将来的标准中,新的int64类型正在考虑之中。到那时,wasm可以使用它。</li>
</ul>
|