Строка — примитивный тип String в JavaScript. Текст в одинарных, двойных кавычках или в обратных штрихах (это шаблонный литерал, template literal) — всё это строки. Размер не ограничен памятью движка, доступ к символу — по индексу s[0], длина — через s.length.
let name = 'Сергей';
let greeting = "Привет, мир!";
let templated = `Текущий пользователь: ${name}`; // Шаблон со встроенной переменной
let multi = `строка
с переносом`; // только обратные штрихи держат переносы
Парадокс строки в JavaScript — она выглядит как данные, но часто приходит вместо них. Из любого внешнего источника всё попадает в код через текст: HTTP-протокол передаёт строки, HTML-атрибуты — строки, localStorage — строки, поле <input> — тоже строка, даже если type="number". И только потом мы решаем, что с этим текстом делать дальше.
Откуда в коде появляются «неправильные» строки
Несколько типичных источников, где значение приходит как строка, но в логике должно быть чем-то другим:
- Поля форм. Любой <input> возвращает .value в виде строки — даже у type="number" и type="checkbox" (у чекбокса есть .checked с булевым, но .value по-прежнему текстовое).
- URL и query-параметры. URLSearchParams.get('page') вернёт "3", флаг ?active=true — строку "true".
- localStorage / sessionStorage. Браузерные хранилища принимают только строки. Положил true — забрал "true"; положил массив — забрал "[object Object]" (поэтому объекты сериализуют через JSON.stringify).
- Атрибуты HTML. data-*-атрибуты и просто атрибуты вроде aria-pressed="true" хранят значения как строки.
- Старые JSON-API. Большие ID и денежные суммы часто приезжают в кавычках, чтобы не терялась точность.
- Текст из DOM. element.textContent и element.innerHTML отдают строку даже там, где визуально вы видите число.
Пять направлений преобразования
Из строки можно сделать любой другой тип. Подробности — в дочерних главах, ниже — короткий обзор каждого направления с типичным сниппетом.
- Строка в число — самый ходовой случай. Способа три: Number("42") (вернёт 42, на любой не-числовой текст даст NaN), parseInt("42px", 10) (читает число до первого нецифрового символа, удобно для CSS-значений), parseFloat("3.14em") (то же с дробной частью). Унарный плюс +x — короткая запись Number(x), но в команде хуже читается.
- Строка в булевое — здесь главная ловушка: Boolean("false") возвращает true. Любая непустая строка считается truthy. Если в строке буквально лежит слово "false" или "0", обычная конверсия их не поймает — нужен явный x === "true" или JSON.parse(x).
- Строка в массив — через [...str] или Array.from(str) — получим массив символов, корректно работающий с emoji и составными графемами. Старый str.split('') разваливает символы вне базовой плоскости Unicode (например, '🇨🇷'.split('') вернёт четыре куска по половине пары).
- Строка в объект — разбор JSON через JSON.parse, парсинг query-параметров через URLSearchParams, разделение по ключ-значение через Object.fromEntries. Самый частый сценарий — ответ от сервера или восстановление состояния из localStorage.
- Строка в специальное значение — пустую "" или текст "null" делаем настоящим null/undefined. Решение через тернарник, if или маппинг.
Три способа сделать обратную задачу — что-то в строку
Часто нужно идти и в другую сторону: число, объект или булево превратить в строку, чтобы вывести в шаблон или передать в URL. Способа три, и они почти эквивалентны.
let n = 42;
String(n) // "42" — самый универсальный, работает даже на null/undefined
n.toString() // "42" — не сработает на null/undefined: TypeError
`${n}` // "42" — template literal, читается ближе к естественному языку
'' + n // "42" — короткая запись, в команде хуже читается
// у toString() есть бонус: вторым аргументом можно задать систему счисления
(255).toString(16) // "ff"
(8).toString(2) // "1000"
По умолчанию выбирай String(x) или шаблонный литерал. .toString() — когда нужна нестандартная база счисления. Конкатенацию через '' + x используют только в коротких хелперах, где хочется сэкономить три символа.
Подводные камни
parseInt без второго аргумента — ошибка ожидания. В современных движках parseInt("08") вернёт 8, но на легаси-окружениях (старый Node, какие-то embedded-сценарии) он трактует ведущий ноль как восьмеричную запись и возвращает 0. Всегда пиши parseInt(x, 10) — явно говорим: десятичная система.
Пустая строка превращается в ноль. Number("") возвращает не NaN, а 0. Это рождает баги в формах: пустое поле, посчитанное как сумма, даёт ноль, а не валидационную ошибку. Перед конверсией обычно делают value.trim() !== "" и только тогда приводят к числу.
Пробельные символы в начале и конце. Number(" 42 ") вернёт 42 — пробелы по краям игнорируются. А вот Number("4 2") — уже NaN: внутри текста пробелы запрещены. Если данные приходят «грязные», обычно сначала чистим: x.trim().replace(/\s+/g, ''), потом конвертируем.
Регистр символов и сравнение. "True", "TRUE" и "true" — три разные строки. Если конвертируешь «флаг из URL» в булево, нормализуй: x.toLowerCase() === "true".
Юникод и длина. "🇨🇷".length вернёт 4, не 2 — флаг состоит из двух кодпойнтов, каждый занимает по surrogate-паре. Считать «настоящие символы» нужно через [...str].length или регэксп с флагом u.