Firefox 27(Nightly) における新たな String.prototype["@@iterator"]
ちょいと面白いものが実装されて、String.prototype["@@iterator"]
がアップデートされてた。
"@@iterator" というのは、ECMAScript 6th におけるイテレータとなるメソッドで、最近注目のジェネレータオブジェクトを返す。*1
で、このジェネレータオブジェクトのnextメソッドが、従来であればインデックス値に沿って順に値を返していたのだが、これからはUnicodeポイントに沿って値を返すようになる。UTF-16 においてサロゲートペアとなるような文字は従来は2文字として扱われていたのが、Unicodeポイントとして1文字として扱われるようになるのだ。
変更されたのはあくまでジェネレータ部分であって、インデックス値の扱いは変わっていないし、length プロパティも従来通りUTF-16換算なので注意。*2
文字 | コードポイント | UTF-16 |
---|---|---|
𠀋 | U+2000B | \uD840\uDC0B |
𡈽 | U+2123D | \uD844\uDE3D |
𡌛 | U+2131B | \uD844\uDF18 |
上記の文字を例にしてみると
あ...orz はてなダイアリーだと ... に変換されちゃうのね...orz 𠀋=𠀋 𡈽=𡈽 𡌛=𡌛 です。
var str = "𠀋𡈽𡌛" console.log("length", str.length); console.log("count", [...str].length); for (var c of str) { console.log(c, c.length); }
これが、以下のように出ることになる。
"length" 6 "count" 3 "𠀋" 2 "𡈽" 2 "𡌛" 2
今まではサロゲートペアまで考慮した文字数のカウントは面倒だったが、上記コードのように[...str].length
と簡単に書ける。
2014-01-06 追記
まだ実装されてないけど、ものかの » Unicodeの特殊な文字 “結合文字列”にあるようなものがると駄目になるので、String.prototype.normalize で正規化する方が良さそう。
よって、もう少しきちんとカウントするには [...str.normalize()].length
が良さそう。
*1:本来なら Symbol という型のプロパティ(文字列ではない)であるが、Firefox の JavaScript エンジンには Symbols が実装されていないので、文字列プロパティとして存在している。
*2:ここの部分に変更が入ることはないと思う。Break the web って怒られちゃう