読者です 読者をやめる 読者になる 読者になる

JS.next

JavaScriptの最新実装情報を追うブログ

String.prototype.normalizeが実装された

★★☆ ES2015 新仕様実装 V8

実装されたメソッド

  • String.prototype.normalize(form = "NFC")
    form(初期値:"NFC")の形式で正規化した文字列を返す


詳細

複雑な文字は、一文字に見えても、文字コード上は複数の構成文字から成り立っている場合がある。
例えば、『』(濁点付き平仮名か)と、『』(平仮名か) +『[U+3099]』(合成用濁点)は、 同じ意味を持ち同じように見えるが、文字コードが異なるためそのままではプログラム上では異なる文字列として扱われてしまう。

ga_NFC = 'が'        // 'が'
ga_NFD = 'か\u3099'  // 'が'

escape(ga_NFC)  // '%u304C'
escape(ga_NFD)  // '%u304B%u3099'

ga_NFC.length  // 1
ga_NFD.length  // 2

ga_NFC == ga_NFD  // false

前者のような形式を(Normalization Form)NFC(Composition:合成)、後者をNFD(Decomposition:分解)と言う。
また、この2つに加えて、文字を基本的な形でのみ持つNFKCNFKDがあり、これらに変換すると英数字等は半角に、カタカナは全角に、縦書用文字は横書用文字に、『』は『1』に、『』は『VII』に、『』はそれぞれ『[]ート』(length:4)と『[+ ]ート』(length:5)になる。
String.prototype.normalizeメソッドは、これら4種類の正規化形式を引数に取り、文字列をその形式で正規化してくれるものである。

ga_norm = ga_NFD.normalize()  // NFCにする時は引数は省略可能

escape(ga_NFD)   // '%u304B%u3099'
escape(ga_norm)  // '%u304C'

ga_NFD.length   // 2
ga_norm.length  // 1

ga_NFD == ga_norm  // false
ga_NFC == ga_norm  // true


応用例

  • 全角数字列を数値に変換する
suuji = '12345'

num = +suuji.normalize('NFKC')  // 12345


  • 時計用ローマ数字の画像を少ない画像を組み合わせて表現する
function toRNumIMG(hour) {
    var roman = 'ⅫⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ'[hour%12]
    var alphas = roman.normalize('NFKC')  // ローマ数字を'I','V','X'に分解する
    for (var html = '', i = 0; i < alphas.length; ++i) {
        html += '<img src="img/'+ alphas[i] +'.jpg">'
    }
    return html
}

toRNumIMG(6)  // '<img src="img/V.jpg"><img src="img/I.jpg">'


もう1つの問題

normalizeメソッドにより、正規化形式の問題に楽に対処できるようになるが、Unicodeにはもう1つサロゲートペアの問題がある。
こちらもES2015で対処しやすくなったので、実装を心待ちにしたい。


実装されたバージョン

V8 3.24.28


参考リンク