IEのための文字列から文字の配列取得処理
javascriptで文字列から文字の配列を得ようとするときにString.prototype.split()
を使用するのは、よくある間違いのようである。
Note: This is not unicode compliant.
"I💖U".split('')
results in the 4 character array ["I", "�", "�", "u"] which can lead to dangerous bugs.
See answers below for safe alternatives.
-- How to get character array from a string?
これは、split
がサロゲートペアを考慮することなしにUTF-16のコードユニット単位に分解するからである。
参照先にもあるように、ES2015をサポートしているブラウザならばspread syntaxで済む。
const a = [...'I💖U'];
そうでない場合、少し調べて見つからなかったのでプログラムを書いてみた。
function eachChar(str, fn) {
var i = 0;
while (i < str.length) {
var code = str.charCodeAt(i++);
if ((code & 0xF800) != 0xD800) fn(String.fromCharCode(code))
else {
var hi = code;
var low = str.charCodeAt(i++);
fn(String.fromCharCode(hi, low));
}
}
}
eachChar
は、文字列str
を構成する文字ごとにコールバック関数fn
を呼び出す高階関数である。String.prototype.charCodeAt()
で指定した位置のコードユニットを取得できるので、参照したコードユニットがハイサロゲートだった場合は後続するローサロゲートをサロゲートペアとして扱っている。また、String.length
がUTF-16のコードユニット数を返すことにも注意が必要である。
各文字に対して一度処理するだけならばこれで充分である。
eachChar('I💖U', console.log);
文字の配列にしたい場合は追加で、以下のようなコードを書けばよい。
function charArray(str) {
var ret = [];
eachChar(str, function(ch) {
ret.push(ch);
});
return ret;
}
const a = charArray('I💖U');
おしまい。