JS строки

Строка в JavaScript — неизменяемая (immutable) последовательность символов Unicode, примитивный тип данных с богатым встроенным API для обработки текста.

Зачем нужно

Строки — один из наиболее часто используемых типов данных: имена, адреса, URL, шаблоны HTML, JSON. Понимание методов строк позволяет без лишнего кода реализовывать поиск, форматирование, валидацию и трансформацию текста. Template literals (шаблонные строки) ES6 упрощают интерполяцию и многострочный текст.

Где используется

  • Форматирование данных для отображения: имена, даты, суммы
  • Работа с URL: парсинг, построение query-параметров
  • Шаблоны: генерация HTML, SQL-запросов (через параметры), сообщений
  • Валидация: проверка email, телефона, длины пароля
  • Парсинг: split по разделителю, извлечение подстрок

Основной контент

Создание и базовые свойства

const s1 = 'одинарные кавычки';
const s2 = "двойные кавычки";
const name = 'Иван';
const s3 = `шаблонная строка: ${name}`; // Template literal

// Длина
console.log('hello'.length); // 5

// Доступ к символу
console.log('hello'[0]);       // 'h'
console.log('hello'.at(-1));   // 'o' (с конца, ES2022)
console.log('hello'.charAt(1)); // 'e'

// Строки неизменяемы — все методы возвращают новую строку
let str = 'Hello';
str[0] = 'J'; // тихо игнорируется
console.log(str); // 'Hello'

Поиск и проверка

const text = 'JavaScript — лучший язык';

// Поиск подстроки
console.log(text.includes('Java'));      // true
console.log(text.startsWith('Java'));    // true
console.log(text.endsWith('язык'));      // true
console.log(text.indexOf('лучший'));     // 14  (-1 если не найдено)
console.log(text.lastIndexOf('а'));      // 22

// Поиск по RegExp
console.log(text.search(/\w+/));  // 0 (индекс первого совпадения)
console.log(text.match(/\w+/g));  // массив всех слов

Трансформация

const raw = '  Hello World  ';

// Приведение регистра
console.log(raw.toLowerCase()); // '  hello world  '
console.log(raw.toUpperCase()); // '  HELLO WORLD  '

// Обрезка пробелов
console.log(raw.trim());        // 'Hello World'
console.log(raw.trimStart());   // 'Hello World  '
console.log(raw.trimEnd());     // '  Hello World'

// Замена
console.log('foo bar foo'.replace('foo', 'baz'));     // 'baz bar foo'
console.log('foo bar foo'.replaceAll('foo', 'baz'));  // 'baz bar baz'

// Разбивка и объединение
console.log('a,b,c'.split(','));   // ['a', 'b', 'c']
console.log(['a','b','c'].join('-')); // 'a-b-c'

// Повторение и дополнение
console.log('*'.repeat(5));         // '*****'
console.log('5'.padStart(3, '0'));   // '005'
console.log('42'.padEnd(5, '.'));    // '42...'

Извлечение подстрок

const str = 'JavaScript';

// slice(start, end) — поддерживает отрицательные индексы
console.log(str.slice(0, 4));  // 'Java'
console.log(str.slice(-6));    // 'Script'
console.log(str.slice(4, -1)); // 'Scrip'

// substring(start, end) — не поддерживает отрицательные (заменяет на 0)
console.log(str.substring(0, 4)); // 'Java'

Template literals

const user = { name: 'Иван', age: 30 };

// Интерполяция
const greeting = `Привет, ${user.name}! Тебе ${user.age} лет.`;

// Многострочность
const html = `
  <div class="card">
    <h2>${user.name}</h2>
    <p>Возраст: ${user.age}</p>
  </div>
`.trim();

// Выражения внутри ${}
const discount = 10;
const price = 100;
console.log(`Итого: ${price * (1 - discount / 100)} руб`); // 'Итого: 90 руб'

// Tagged templates
function highlight(strings, ...values()) {
  return strings.reduce((result, str, i) => {
    return result + str + (values[i] ? `<b>${values[i]}</b>` : '');
  }, '');
}
console.log(highlight`Привет, ${user.name}! Возраст: ${user.age}`);
// 'Привет, <b>Иван</b>! Возраст: <b>30</b>'

Частые ошибки

  • Сравнение через ==: '5' == 5 — true из-за приведения. Используйте ===.
  • Мутация строки: строки иммутабельны, все методы возвращают новую строку — результат нужно сохранять.
  • indexOf возвращает -1, не false: if (str.indexOf('x')) — true даже если результат -1. Проверяйте !== -1 или используйте includes.
  • Длина строки с emoji: '😀'.length === 2 (два UTF-16 code unit). Для работы с Unicode-символами используйте [...'😀'].length === 1.

Связанные темы

Ресурсы


🎓 Источник: Work with strings, templates and Unicode in JavaScript

  • 📅 2018-10-18 · YouTube
  • Тезисы: строки в JS хранятся в UTF-16. Template literals — это синтаксический сахар; tagged templates позволяют делать DSL (SQL builders, i18n). Unicode-нормализация через String.prototype.normalize()

⚡ Источник: Тип String согласно спецификации ECMAScript. Часть 1 из 3 · AsForJS

  • 📅 2025-06-14 · YouTube
  • Тезисы:
    • В спеке String — последовательность 16-битных целых (UTF-16 code units), а НЕ символов
    • '😀'.length === 2 — это 2 surrogate pair, не баг
    • Базовый набор операций: [[Get]] по индексу, length, Symbol.iterator (умеет работать с surrogate)

⚡ Источник: Тип String и его две основные проблемы. Часть 2 из 3 · AsForJS

  • 📅 2025-06-23 · YouTube
  • Тезисы: проблема 1 — surrogate pairs (emoji, кириллица в редких случаях). Проблема 2 — normalization (NFC vs NFD): два визуально одинаковых "é" могут быть 'é' и 'é'

⚡ Источник: String in wild. Часть 3 из 3 · AsForJS

  • 📅 2025-06-26 · YouTube
  • Тезисы: в V8 строки хранятся как ConsString (склейка), SlicedString (срез), ExternalString (от C++). str1 + str2 создаёт ConsString с O(1), но первое чтение требует O(n) flatten

⚡ Источник: Побалакаємо щодо String в JavaScript · AsForJS

  • 📅 2025-06-04 · YouTube
  • Тезисы: обзорная беседа о специфике String — почему 'a' === 'a' (string interning в V8), почему new String('a') !== 'a' (object vs primitive)

⚡ Источник: JavaScript template literal или 100+1 способ вызвать функцию · AsForJS

  • 📅 2023-05-29 · YouTube
  • Тезисы: tagged template literal — это вызов функции с особыми аргументами: [strings, ...values()]. strings имеет .raw для доступа к исходному тексту. Это основа для GraphQL/styled-components

⚡ Источник: Задача с собеседования о разбиении текста на строки · AsForJS

  • 📅 2023-06-12 · YouTube
  • Тезисы: разбор word-wrap. Подход: парсер по словам, не по индексам. Учёт переносов и многострочного режима

⚡ Источник: ⎡RegExp 05⎦ JavaScript Strings и Unicode, UTF-16 · AsForJS

  • 📅 2023-07-04 · YouTube
  • Тезисы: Unicode code point ≠ UTF-16 code unit. \u{1F600} (code point) vs 😀 (две UTF-16 unit). RegExp flag u включает code point matching