TextEncoder.encodeInto()
========================

**`TextEncoder.encodeInto()`** 方法接受一个要编码的字符串和一个目标 `Uint8Array`，将生成的 UTF-8 编码的文本放入目标数组中，并返回一个指示编码进度的字典对象。这相比于旧的 `encode()` 方法性能更高——尤其是当目标缓冲区是 WASM 堆视图时。

语法
--


```js
encodeInto(string, uint8Array)
```

### 参数

`string`

一个字符串，包含将要编码的文本。

`uint8Array`

一个 `Uint8Array` 对象实例，用于将生成的 UTF-8 编码的文本放入其中。

### 返回值

一个对象，包含两个参数。

`read`

已经从源字符串中转换为 UTF-8 的，使用 UTF-16 编码的码元数。如果 `uint8Array` 没有足够的空间，则此值可能小于 `string.length`。

`written`

在目标 `Uint8Array` 中修改的字节数。写入的的字节确保形成完整的 UTF-8 字节序列。

编码到特定的位置
--------

*encoder*`.encodeInto()` 总是将它输出的结果放在数组的开头。然而，有时使输出从一个指定的索引开始很有用。解决方案是：`TypedArray.prototype.subarray()`：


```js
const encoder = new TextEncoder();

function encodeIntoAtPosition(string, u8array, position) {
  return encoder.encodeInto(
    string,
    position ? u8array.subarray(position | 0) : u8array,
  );
}

const u8array = new Uint8Array(8);
encodeIntoAtPosition("hello", u8array, 2);
console.log(u8array.join()); // 0,0,104,101,108,108,111,0
```

缓冲区大小
-----

转换一个 JavaScript 字符串 `s` 到 UTF-8 序列时，完全转换输出所需的空间从不会小于 `s.length` 个字节，也从不会大于 `s.length * 3` 字节。如果预计输出到缓冲区（通常是在 WASM 堆中）的生命周期很短，则可以为输出分配 `s.length * 3` 字节的空间，这样就能保证在第一次尝试中转换整个字符串。注意，`s.length * 3` 的情况是很少见的，因为很少有字符串中一定包含扩展之后为 3 个字节的字符。长文本的长度将不太可能超过 `s.length * 2` 个字节。因此，更乐观的方法可能是分配 `s.length * 2 + 5`个字节的空间，并且在极少数的情况下（乐观分配的方法出现错误）进行重新分配。

如果预计输出的生命周期很长，则可以计算最小分配空间为 `roundUpToBucketSize(s.length)`，最大分配空间为 `s.length * 3`，并且选择一个阈值 `t`（作为内存使用和速度之间的折衷方案），使得 `roundUpToBucketSize(s.length) + t >= s.length * 3` 时，分配 `s.length * 3` 的空间。否则，首先为 `roundUpToBucketSize(s.length)` 分配空间并进行转换。如果返回的字典对象中的 `read` 的大小为 `s.length`，则表示转换完成。如果不是，将目标的缓冲区的大小重新分配为 `written + (s.length - read) * 3`，并从字符串 `s` 中的索引 `read` 处开始取子字符串，并从目标缓冲区的索引 `written` 处开始取子缓冲区进行转换。

上述 `roundUpToBucketSize()` 函数，用于将空间向上舍入到分配器的桶大小。例如，如果你的 Wasm 分配器使用 2 的幂次方桶，则 `roundUpToBucketSize()` 应该返回该参数（如果它是 2 的幂次方的话，否则返回下一个 2 的幂次方）。如果 Wasm 分配器的行为未知，则 `roundUpToBucketSize()` 应为恒等函数。

如果你分配器的行为未知，但是你可能想要进行多达两次重新分配，并使得第一次重分配的步骤将*剩余未转换*的长度乘以 2 而不是 3。然而，在这种情况下，将*已经写入*缓冲区的长度乘以 2 通常是没有意义的，因为在这种情况下，如果发生第二次重分配，与原始长度乘 3 相比，它将总是过度分配。上述建议假设你不需要为 0 终止符分配空间。也就是说，在 WASM 方面，你正在使用 Rust 字符串或者一个不以 0 终止的 C++ 类。如果你正在使用 C++ `std::string` 标准库，即使逻辑长度已经向你展示，当计算向上舍入到分配器的桶大小的时候，你还是需要去考虑额外的终止符字节。请参阅下一节有关 C 字符串的内容。

没有 0 终止符
--------

如果输入字符串在输入中包含字符 U+0000，`encodeInto()` 将在输出中写入一个 0x00 字节。`encodeInto()` *不会*在逻辑输出后写入 C 风格的 0x00 标记字节。

如果你的 Wasm 程序使用 C 字符串，那么你有职责去写 `0x00` 的标记，并且如果你的 JavaScript 字符串包含 `U+0000`，则无法阻止 Wasm 程序看到逻辑截断的字符串。观察：


```js
const encoder = new TextEncoder();

function encodeIntoWithSentinel(string, u8array, position) {
  const stats = encoder.encodeInto(
    string,
    position ? u8array.subarray(position | 0) : u8array,
  );
  if (stats.written < u8array.length) u8array[stats.written] = 0; // append null if room
  return stats;
}
```

示例
--


```html
<p class="source">This is a sample paragraph.</p>
<p class="result"></p>
```



```js
const sourcePara = document.querySelector(".source");
const resultPara = document.querySelector(".result");
const string = sourcePara.textContent;

const textEncoder = new TextEncoder();
const utf8 = new Uint8Array(string.length);

const encodedResults = textEncoder.encodeInto(string, utf8);
resultPara.textContent +=
  `Bytes read: ${encodedResults.read}` +
  ` | Bytes written: ${encodedResults.written}` +
  ` | Encoded result: ${utf8}`;
```

规范
--

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textencoder-encodeinto① |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 属于 `TextEncoder` 接口
* `TextEncoder.encode()`