
Перебор строк в JavaScript необходим при анализе пользовательского ввода, разборе протоколов, подготовке данных для алгоритмов. Поведение циклов и методов зависит от структуры строки, включая расположение surrogate-пар и наличие символов, занимающих больше одного кода UTF-16.
При работе со строками важно учитывать разницу между индексами и реальными символами. Например, эмодзи и некоторые иероглифы занимают две кодовые единицы, поэтому простое обращение по индексу возвращает часть символа. Это влияет на выбор приёма: нужны ли отдельные кодовые точки, пары значений или последовательный доступ без искажений.
Выбор подхода опирается на задачу: постсимвольный анализ, преобразование строки в массив, контроль кодовых значений или работа с итератором. Каждый способ даёт собственный уровень доступа – от привычного цикла до обхода с учётом Unicode.
Перебор символов через цикл for с доступом по индексу
Цикл for с индексами позволяет обращаться к каждому элементу строки через синтаксис str[i]. Этот способ подходит для анализа ASCII-символов и большинства BMP-символов, но требует внимания при работе с суррогатными парами.
Пример базового перебора:
const str = "JavaScript";
for (let i = 0; i < str.length; i++) {
console.log(str[i]);
}
Рекомендации при использовании:
- Использовать i < str.length для корректного обхода всех индексов.
- При необходимости обработки emoji или символов вне BMP проверять codePointAt(i).
- Для модификации символов внутри строки создавать массив через split('') или использовать substring, так как строки неизменяемы.
Преимущества метода:
- Простой и читаемый синтаксис.
- Прямой доступ к индексу позволяет использовать его для вычислений и условия.
- Подходит для совместимости с любыми версиями JavaScript без дополнительных библиотек.
Недостаток – при работе с символами, требующими две кодовые единицы UTF-16, перебор по индексу возвращает только часть символа, что может привести к искажению данных при обработке текста с emoji или редкими иероглифами.
Использование цикла for.of для обхода Unicode-символов
Цикл for...of перебирает строку по реальным символам, корректно обрабатывая суррогатные пары и символы вне BMP. Это делает его предпочтительным при работе с emoji, редкими иероглифами и комбинированными символами.
Пример использования:
const str = "A😊Б𐍈";
for (const char of str) {
console.log(char);
}
Особенности метода:
- Каждая итерация возвращает полный символ, даже если он занимает две кодовые единицы UTF-16.
- Поддерживает любые стандартные строковые операции: char.toUpperCase(), char.normalize().
- Не требует явного контроля длины строки, обход происходит до конца автоматически.
Рекомендации по использованию:
- Использовать при обработке текста с международными символами или emoji.
- Для работы с индексами комбинировать с Array.from(str), если нужен доступ к позиции символа.
- Избегать при простых ASCII-строках, если критична производительность, так как цикл немного медленнее обхода по индексам.
Применение метода split() для работы с массивом символов
Метод split('') превращает строку в массив отдельных символов, позволяя использовать массивные методы перебора: forEach, map, filter. Это удобно при массовой обработке и трансформации текста.
Пример базового применения:
const str = "JavaScript";
const chars = str.split('');
chars.forEach(char => console.log(char));
Особенности метода:
- Создаёт новый массив, поэтому исходная строка остаётся неизменной.
- Подходит для применения стандартных массивных операций, включая сортировку и фильтрацию символов.
- Не учитывает суррогатные пары: emoji и редкие символы будут разделены на части.
Рекомендации по использованию:
- Применять для работы с текстом, где важен каждый символ как элемент массива.
- Для Unicode-символов вне BMP использовать Array.from(str) вместо split(''), чтобы сохранить целостность символов.
- Использовать совместно с map() или filter() для массовых изменений без циклов.
Итерация строки через метод charAt() в цикле

Метод charAt(index) возвращает символ по указанному индексу, что позволяет безопасно обходить строку без прямого обращения через квадратные скобки. Этот подход сохраняет совместимость со старыми версиями JavaScript.
Пример использования в цикле:
const str = "Hello";
for (let i = 0; i < str.length; i++) {
console.log(str.charAt(i));
}
Особенности метода:
- Возвращает пустую строку, если индекс выходит за пределы длины строки.
- Подходит для обработки символов BMP, но для суррогатных пар возвращает только первую кодовую единицу.
- Можно комбинировать с substring() или slice() для получения диапазона символов.
Рекомендации:
- Использовать, когда требуется совместимость с устаревшими браузерами.
- Для текстов с Unicode-символами вне BMP предпочесть for...of или Array.from().
- Метод удобен для последовательного обхода без создания массива, что экономит память при длинных строках.
Обход строки с помощью метода forEach() после преобразования в массив
Метод forEach() применяется к массиву символов, полученному из строки через split('') или Array.from(). Он позволяет выполнять функции для каждого символа без явного управления индексами.
Пример применения:
const str = "Привет";
Array.from(str).forEach(char => console.log(char));
Особенности метода:
- Array.from() сохраняет целостность Unicode-символов вне BMP, в отличие от split('').
- Можно применять любые методы массива: map, filter, reduce.
- Не возвращает новый массив, поэтому изменения должны выполняться внутри функции или через map.
Рекомендации:
- Использовать при необходимости последовательной обработки каждого символа без контроля индексов.
- Для работы с emoji и сложными символами применять Array.from(), чтобы избежать разделения суррогатных пар.
- Не использовать в критичных по производительности участках для длинных строк, так как метод создаёт дополнительный массив.
Перебор кодовых точек с использованием метода codePointAt()

Метод codePointAt(index) возвращает числовое значение Unicode-символа на указанной позиции. Это позволяет корректно обрабатывать символы вне BMP, включая emoji и редкие иероглифы, которые занимают две кодовые единицы UTF-16.
Пример перебора кодовых точек в цикле:
const str = "A😊Б𐍈";
for (let i = 0; i < str.length; i++) {
const code = str.codePointAt(i);
console.log(code.toString(16));
if (code > 0xffff) i++; // пропуск второй кодовой единицы суррогатной пары
}
Рекомендации по использованию:
- Использовать, когда необходим точный анализ символов по их Unicode-кодам.
- При обходе строк с символами вне BMP учитывать, что некоторые символы занимают две позиции в строке.
- Совмещать с String.fromCodePoint() для обратного преобразования числовых кодов в символы.
Сравнительная таблица подходов перебора с учётом кодовых точек:
| Метод | Обрабатывает суррогатные пары | Доступ к Unicode-коду | Примечания |
|---|---|---|---|
| charAt() | Нет | Нет | Возвращает часть суррогатной пары |
| for...of | Да | Нет напрямую | Возвращает целые символы |
| codePointAt() | Да (при корректной обработке индексов) | Да | Требуется пропуск второй кодовой единицы суррогатной пары |
Работа с итератором строки через метод Symbol.iterator

Метод Symbol.iterator возвращает итератор строки, который позволяет проходить по каждому символу с учётом суррогатных пар и комбинированных Unicode-символов. Это обеспечивает точную обработку любых символов, включая emoji и редкие иероглифы.
Пример работы с итератором:
const str = "A😊Б𐍈";
const iterator = str[Symbol.iterator]();
let result = iterator.next();
while (!result.done) {
console.log(result.value);
result = iterator.next();
}
Особенности метода:
- Каждый вызов next() возвращает объект { value, done }, где value – символ строки.
- Итератор корректно обрабатывает любые Unicode-символы без необходимости вручную пропускать суррогатные пары.
- Поддерживает последовательное использование в циклах и совместно с for...of или spread-оператором.
Рекомендации по использованию:
- Применять, когда требуется контроль над шагами итерации и возможность досрочного завершения.
- Удобно для потоковой обработки длинных строк или динамических данных.
- Использовать в сочетании с другими методами преобразования для комбинированных операций с символами.
Вопрос-ответ:
В чём разница между перебором строки через цикл for и использованием for...of?
Цикл for перебирает строку по индексам и возвращает отдельные UTF-16 единицы, что может разделять суррогатные пары. Цикл for...of обходит строку по реальным символам, включая emoji и символы вне BMP, без необходимости контролировать длину и индексы вручную.
Как сохранить целостность Unicode-символов при преобразовании строки в массив?
Метод split('') разделяет строку на отдельные кодовые единицы и может разрывать суррогатные пары. Чтобы сохранить целостность символов, используют Array.from(str) или цикл for...of, которые корректно обрабатывают символы вне базовой многоязычной плоскости.
Почему в некоторых случаях перебор с charAt() может давать некорректные результаты для emoji?
Метод charAt() возвращает символ по индексу UTF-16. Emoji и редкие иероглифы могут занимать две кодовые единицы. В этом случае charAt() вернёт только часть символа, что приводит к некорректному отображению или обработке, если не учитывать это с помощью codePointAt() или for...of.
В каких ситуациях удобно использовать codePointAt() для перебора строки?
Метод codePointAt() возвращает числовое значение Unicode-символа и позволяет точно работать с символами вне BMP. Его применяют при анализе текста на уровне кодов символов, для проверки диапазонов, сортировки по Unicode или преобразования кодов обратно в символы через String.fromCodePoint().
Можно ли прерывать обход строки, используя итератор Symbol.iterator?
Да, итератор, возвращаемый через Symbol.iterator, предоставляет объект с полями value и done. Цикл обхода можно завершить досрочно, просто не вызывая next() дальше или прерывая цикл, что удобно для поиска определённого символа без полного прохода строки.
Как корректно перебрать строку с emoji и редкими иероглифами в JavaScript?
Для строк, содержащих символы вне базовой многоязычной плоскости, простое обращение по индексу или методы вроде charAt() могут возвращать лишь часть символа, так как такие символы занимают две кодовые единицы UTF-16. Чтобы получать полные символы, используют цикл for...of или преобразование строки через Array.from(). При необходимости работы с кодами символов применяют codePointAt() и String.fromCodePoint(), что позволяет правильно обрабатывать и преобразовывать сложные Unicode-символы без потери информации.
