Если кратко: JavaScript не поддерживает суррогатные пары. Что в общем и правильно, так как в большинстве случаев это не нужно, а только лишние расходы. Однако, в меньшинстве случаев из-за этого придётся повозиться.
Теперь рассмотрим подробнее, что означает этот набор слов.
UTF-16 vs UCS-2
Как, наверняка, знают все здесь присутствующие, строки в компьютерах представляются, как последовательность байтиков. А каким образом эти байтики соответствуют буковкам, это определяет кодировка.
Старые добрые кодировки, вроде Windows-1251 были однобайтными. Одному символу — один байт. Работать с ними было одно удовольствие. Хочешь узнать длину строки (количество символов): это просто количество байт. Нужен 5-й символ: просто нужен пятый байт от начала строки. Единственный минус: в нашем многополярном мире 256 различных символов, это слишком мало. Особенно для китайцев с их тысячами иероглифов.
Поэтому теперь мы все любим Unicode. В юникоде много разных кодировок на все случаи жизни. Вот, например, UTF-8: в нём можно закодировать любой Unicode-символ хитрой переменного размера последовательностью байт. При этом базовая ASCII в нём остаётся такого же вида, как и в старых кодировках. Можно читать английские тексты не думая о кодировках, исходники программ и HTML/XML файлы сохраняют свою структуру, а наиболее популярные символы занимают меньше места, чем всякие иероглифы, что тоже приятно.
Неудобно его только обрабатывать. Чтобы узнать длину строки или найти N-й символ, нужно проходить по всем байтам сначала и производить над каждым разные вычисления. Что напрягает. Поэтому в памяти строки лучше хранить в какой-нибудь кодировке фиксированного размера.
Остальной текст под катом