Строка — примитивный тип 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.