TextEncoder - 将代码点流作为输入,并输出 UTF-8 字节流

TextEncoder 将代码点流作为输入,并输出 UTF-8 字节流。

注意GitHub 上有一个 polyfill 实现来支持非 UTF-8 文本编码。

实例

const encoder = new TextEncoder()
const view = encoder.encode('€')
console.log(view); // Uint8Array(3) [226, 130, 172]

构造函数

TextEncoder()

返回一个新构造的 TextEncoder,它将用于生成 UTF-8 编码的字节流。

属性

TextEncoder 接口不继承任何属性。

TextEncoder.prototype.encoding 只读

始终返回 “utf-8”。

方法

TextEncoder 接口不继承任何方法。

TextEncoder.prototype.encode()

接受一个 USVString 作为输入,并返回包含 utf-8 编码文本的 Uint8Array

TextEncoder.prototype.encodeInto()

接受一个 USVString 用于编码,以及一个 Uint8Array 用于放入生成的 UTF-8 编码文本,并返回指示编码进度的字典对象。比起较旧的 encode() 方法,它的性能可能更高。

Polyfill

下面的 polyfill 与标准相符,因此仅支持 UTF-8。它旨在在 IE5 中 “开箱即用”。但是,在 IE5-IE9 中,它将返回常规数组而不是 TypedArray。在这种情况下,对于大的字符串来说,使用 polyfill 可能是不切实际的。最后,请注意,您应该通过一个 minifier(尤其是闭包编译器)运行以下代码,以将 0x1e << 3 之类的序列转换为 0xf0。这些序列没有预先计算,因为它们用于说明 polyfill 的工作原理。

if (typeof TextEncoder === "undefined") {
    TextEncoder=function TextEncoder(){};
    TextEncoder.prototype.encode = function encode(str) {
        "use strict";
        var Len = str.length, resPos = -1;
        // Uint8Array 的长度必须至少是字符串长度的 3 倍,
        // 因为无效的 UTF-16 会占用 3 个 UTF-8 字符的等价空间以对其进行正确编码。
        // 然而,Array 会自动扩展长度,1.5 倍应该是大多数情况下的平衡选择。
        var resArr = typeof Uint8Array === "undefined" ? new Array(Len * 1.5) : new Uint8Array(Len * 3);
        for (var point=0, nextcode=0, i = 0; i !== Len; ) {
            point = str.charCodeAt(i), i += 1;
            if (point >= 0xD800 && point <= 0xDBFF) {
                if (i === Len) {
                    resArr[resPos += 1] = 0xef/*0b11101111*/; resArr[resPos += 1] = 0xbf/*0b10111111*/;
                    resArr[resPos += 1] = 0xbd/*0b10111101*/; break;
                }
                // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
                nextcode = str.charCodeAt(i);
                if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
                    point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
                    i += 1;
                    if (point > 0xffff) {
                        resArr[resPos += 1] = (0x1e/*0b11110*/<<3) | (point>>>18);
                        resArr[resPos += 1] = (0x2/*0b10*/<<6) | ((point>>>12)&0x3f/*0b00111111*/);
                        resArr[resPos += 1] = (0x2/*0b10*/<<6) | ((point>>>6)&0x3f/*0b00111111*/);
                        resArr[resPos += 1] = (0x2/*0b10*/<<6) | (point&0x3f/*0b00111111*/);
                        continue;
                    }
                } else {
                    resArr[resPos += 1] = 0xef/*0b11101111*/; resArr[resPos += 1] = 0xbf/*0b10111111*/;
                    resArr[resPos += 1] = 0xbd/*0b10111101*/; continue;
                }
            }
            if (point <= 0x007f) {
                resArr[resPos += 1] = (0x0/*0b0*/<<7) | point;
            } else if (point <= 0x07ff) {
                resArr[resPos += 1] = (0x6/*0b110*/<<5) | (point>>>6);
                resArr[resPos += 1] = (0x2/*0b10*/<<6)  | (point&0x3f/*0b00111111*/);
            } else {
                resArr[resPos += 1] = (0xe/*0b1110*/<<4) | (point>>>12);
                resArr[resPos += 1] = (0x2/*0b10*/<<6)    | ((point>>>6)&0x3f/*0b00111111*/);
                resArr[resPos += 1] = (0x2/*0b10*/<<6)    | (point&0x3f/*0b00111111*/);
            }
        }
        if (typeof Uint8Array !== "undefined") return resArr.subarray(0, resPos + 1);
        // else // IE 6-9
        resArr.length = resPos + 1; // 移除额外的内容
        return resArr;
    };
    TextEncoder.prototype.toString = function(){return "[object TextEncoder]"};
    try { // Object.defineProperty 仅适用于 IE8 中的 DOM 原型
        Object.defineProperty(TextEncoder.prototype,"encoding",{
            get:function(){if(TextEncoder.prototype.isPrototypeOf(this)) return"utf-8";
                           else throw TypeError("Illegal invocation");}
        });
    } catch(e) { /*IE6-8 fallback*/ TextEncoder.prototype.encoding = "utf-8"; }
    if(typeof Symbol!=="undefined")TextEncoder.prototype[Symbol.toStringTag]="TextEncoder";
}

源码:https://github.com/anonyco/FastestSmallestTextEncoderDecoder

规范

规范 状态 备注
Encoding
TextEncoder 的定义
现行的标准 初始定义。

桌面浏览器兼容性

特性ChromeEdgeFirefoxInternet ExplorerOperaSafari
基础支持3879

19

181

不支持2510.1
TextEncoder() 构造函数

533

38 — 534

793

485

38 — 486

19 — 387

181

不支持2510.1
encode3879

19

181

不支持2510.1
encodeInto747966 不支持 不支持 不支持
encoding3879

19

181

不支持2510.1
在 Worker 中可用387920 不支持2510.1

移动浏览器兼容性

特性AndroidChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
基础支持3838 未知

19

181

未知 支持10.3
TextEncoder() 构造函数3838 未知

485

38 — 486

19 — 387

181

未知 未知10.3
encode3838 未知

19

181

未知 支持10.3
encodeInto7474 未知66 未知 不支持 不支持
encoding3838 未知

19

181

未知 支持10.3
在 Worker 中可用3838 未知20 未知 未知10.3

1. Firefox 18 实现了该规范的早期版本,与现有版本稍有不同。

2. 从 util 模块导出,但不是全局可用。

3. 不接受参数。仅支持 utf-8 编码。

4. 对于未知的编码类型,引发 RangeError 异常

5. 构造函数接受编码类型标签参数,但该值将被忽略。仅支持 utf-8 编码

6. 如果编码类型标签参数无效,则将引发 RangeError 异常。

7. 如果编码类型标签参数无效,则将引发 TypeError 异常。

相关链接