Если в вашей строке есть не-bmp символы, это немного сложнее ...
Поскольку javascript кодирует UTF-16, а «символ» представляет собой 2-байтовый стек (16 бит), все многобайтовые символы (3 и более байтов) не будут работать:
<script type="text/javascript">
var nonBmpString = "foo€";
console.log( nonBmpString.length );
// will output 5
</script>
Символ "€" имеет длину 3 байта (24 бита). Javascript интерпретирует его как 2 символа, потому что в JS символ представляет собой 16-битный блок.
Таким образом, чтобы правильно получить байтовый размер смешанной строки, мы должны кодировать нашу собственную функцию fixedCharCodeAt ();
function fixedCharCodeAt(str, idx) {
idx = idx || 0;
var code = str.charCodeAt(idx);
var hi, low;
if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
hi = code;
low = str.charCodeAt(idx + 1);
if (isNaN(low)) {
throw 'Kein gültiges Schriftzeichen oder Speicherfehler!';
}
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
// We return false to allow loops to skip this iteration since should have already handled high surrogate above in the previous iteration
return false;
/*hi = str.charCodeAt(idx-1);
low = code;
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;*/
}
return code;
}
Теперь мы можем считать байты ...
function countUtf8(str) {
var result = 0;
for (var n = 0; n < str.length; n++) {
var charCode = fixedCharCodeAt(str, n);
if (typeof charCode === "number") {
if (charCode < 128) {
result = result + 1;
} else if (charCode < 2048) {
result = result + 2;
} else if (charCode < 65536) {
result = result + 3;
} else if (charCode < 2097152) {
result = result + 4;
} else if (charCode < 67108864) {
result = result + 5;
} else {
result = result + 6;
}
}
}
return result;
}
Кстати ...
Вы не должны использовать метод encodeURI, потому что это встроенная функция браузера;)
Больше вещей:
Приветствия
frankneff.ch / @frank_neff