Один приятный и быстрый способ - использовать комбинацию encodeURI и unescape:
t=[];
for(s=unescape(encodeURI("zażółć gęślą jaźń")),i=0;i<s.length;++i)
t.push(s.charCodeAt(i));
t
[122, 97, 197, 188, 195, 179, 197, 130, 196, 135, 32, 103, 196, 153, 197, 155, 108, 196, 133, 32, 106, 97, 197, 186, 197, 132]
Возможно, нужно какое-то объяснение, почему, черт возьми, это работает, поэтому позвольте мне разбить его на шаги:
encodeURI("zażółć gęślą jaźń")
возвращает
"za%C5%BC%C3%B3%C5%82%C4%87%20g%C4%99%C5%9Bl%C4%85%20ja%C5%BA%C5%84"
которая - если вы внимательно посмотрите - это исходная строка, в которой все символы со значениями> 127 были заменены (возможно, более чем одним) шестнадцатеричным байтовым представлением.
Например, буква "ż" стала "% C5% BC". Дело в том, что encodeURI избегает также некоторых обычных символов ascii, таких как пробелы, но это не имеет значения. Важно то, что в этот момент каждый байт исходной строки представлен либо дословно (как в случае с «z», «a», «g» или «j»), либо в виде последовательности байтов в процентах ( как и в случае с «ż», который изначально составлял два байта 197 и 188 и был преобразован в% C5 и% до н.э).
Теперь мы применяем unescape:
unescape("za%C5%BC%C3%B3%C5%82%C4%87%20g%C4%99%C5%9Bl%C4%85%20ja%C5%BA%C5%84")
что дает
"zażóÅÄ gÄÅlÄ jaźÅ"
Если вы не являетесь носителем польского языка, вы можете не заметить, что этот результат фактически отличается от оригинального "zażółć gęślą jaźń". Для начала у него разное количество символов :)
Конечно, вы можете сказать, что эти странные версии большой буквы A не относятся к стандартному набору ascii. На самом деле это «Å» имеет значение 197. (что в шестнадцатеричном формате точно C5).
Теперь, если вы похожи на меня, вы спросите себя: подождите минуту ... если это действительно последовательность байтов со значениями 122, 97, 197, 188, и JS действительно использует UTF, тогда почему я видите символы "ż", а не оригинал "ż"?
Хорошо, дело в том (я верю), что эта последовательность 122, 97, 197, 188 (которую мы видим при применении charCodeAt) - это не последовательность байтов , а последовательность коды . Символ «Å» имеет код 197, но на самом деле его последовательность длиной два байта: C3 85.
Итак, хитрость работает, потому что unescape обрабатывает числа, встречающиеся в процентно-кодированной строке, как коды, а не как байтовые значения, или, если быть более точным: unescape ничего не знает о многобайтовых символах, поэтому, когда он декодирует байты один за другим обработка значений ниже 128 просто великолепна, но не так хороша, когда они выше 127, и многобайтовая - unescape в таких случаях просто возвращает многобайтовый символ, который имеет код, равный запрошенному значению байта. Эта «ошибка» на самом деле полезная функция.