JavaScriptの文字コード・バイト配列絡みの忘却録

型と文字コード

文字コード補足
StringUnicode(※)DOMString。エンコード方式はUTF-16。
Blob-String は UTF-8 に変換される
ソースコード-ウェブでは、 UTF-8N が一般的

※ JavaScript は、通常 UTF-16 のエンコード方式を採用している。
 ただし、 UTF-8 のエンコード方式を使用していることもある。
 例:下記の例などで独自に変換した場合

TextEncoder / TextDecoder

var text = "文字列";

// String(UTF-16) -> TypedArray<Uint8Array>(UTF-8)
var encoder = new TextEncoder('utf-8');
var ab8 = encoder.encode(text);

// TypedArray<Uint8Array>(UTF-8) -> String(UTF-16)
var decoder = new TextDecoder('utf-8');
var utf16 = decoder.decode(ab8);

※ UTF-8 以外にも対応しています。
 Encoding API Encodings - Web APIs | MDN

UTF-8/UTF-16 への変換

var text = "文字列";

// String(UTF-16) -> String(UTF-8)
var utf8 = unescape(encodeURIComponent(text));

// String(UTF-8) -> String(UTF-16)
var utf16 = decodeURIComponent(escape(utf8));

BASE64 への変換

var text = "文字列";

// String(UTF-16) -> String(UTF-8) -> BASE64(UTF-8)
var base64 = btoa(unescape(encodeURIComponent(text)));

// BASE64(UTF-8) -> String(UTF-8) -> String(UTF-16)
var utf16 = decodeURIComponent(escape(atob(base64)));

TypedArray への変換

var text = "文字列";

// String(UTF-16) -> String(UTF-8) -> TypedArray<Uint8Array>(UTF-8)
var ab8 = Uint8Array.from(unescape(encodeURIComponent(text)).split(''), c => c.charCodeAt(0));

// TypedArray<Uint8Array>(UTF-8) -> Uint8Array(UTF-8) -> String(UTF-8) -> String(UTF-16)
var utf16 = decodeURIComponent(escape(String.fromCharCode.apply('', ab8)));

Blob への変換

// String(UTF-16) -> Blob(UTF-8N)
var text = '文字列';
var blob8n = new Blob([text], {'type':'text/plain'});

// String(UTF-16) -> Blob(UTF-8)
var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
var text = '文字列';
var blob8 = new Blob([bom, text], {'type':'text/plain'});

// Blob(UTF-8N/UTF-8) -> ArrayBuffer(UTF-8N/UTF-8) 
//                    -> TypedArray<Uint8Array>(UTF-8) -> String(UTF-8) -> String(UTF-16)
var blob = blob8n;//blob8;
var ab8 = await blob.arrayBuffer();
var utf16 = decodeURIComponent(escape(String.fromCharCode.apply('', new Uint8Array(ab8))));

Blobは、 UTF-16 の文字列でも UTF-8 でエンコードして出力します。

マルチバイト文字の文字列長

var emoji = "😉😉😉"
console.log(emoji.length);            // 6
console.log(Array.from(emoji).length);// 3
console.log([...emoji].length);       // 3

※スプレッド構文:[...iterableObj]
※絵文字だけでなく、韓国語やタイ語などで同様現象が発生する。

ソースコードの文字コード

ウェブ関連のソースコードの文字コードは、 UTF-8N が一般的です。

BOM ありだと処理できないシステムがあるため、 UTF-8N なんだとか。(BOM の文字化けとかが起こる)

ただし、 Microsoft Excel で CSV ファイルを扱う場合は、 UTF-8 にしないと、 Shift-JIS 扱いされて文字化けします。

URL エンコード(パーセントエンコーディング)

URI で使用できない文字を使う際に行われるエンコードです。 URL 関連などで使用されます。

var url0 = 'https://.../バグ取りの日々.html';
var url1 = encodeURIComponent(url0);
console.log(url1);            // https%3A%2F%2F...%2F%E3%83%90%E3%82%B0%E5%8F%96%E3%82%8A%E3%81%AE%E6%97%A5%E3%80%85.html

var url2 = decodeURIComponent(url1);
console.log(url2);            // https://.../バグ取りの日々.html

※「encodeURI」と「encodeURIComponent」の違いは、#$&+,/:;=?@を含めてエンコードするか否かです
※「application/x-www-form-urlencoded」では、半角スペース(%20)が「+」に変換される

Punycode

日本語ドメイン名などの国際化ドメイン名に使用されている文字符号化方式です。

HTML特殊文字

HTML には、特別に変換された文字が存在します。&amp;&#12290;などです。次に変換処理の参考リンクを示します。

参考