← JavaScript/Строки#71 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: как учить JavaScriptПрактика: JS базаПрактика: async и сетьТермин: Closure

Строки

Реальная проблема: данные из форм и API

В Telegram при регистрации вы вводите имя — возможно с пробелами по краям, в разном регистре. Ваш код должен нормализовать это, извлечь инициалы, проверить длину, сформатировать отображение. Строки — это хлеб и масло веб-разработчика: почти каждый запрос к API возвращает строки, почти каждая форма отправляет строки.

Что такое строка в JS

Строки иммутабельны — нельзя изменить символ по индексу. Каждый метод возвращает новую строку. Строки — Unicode, что значит поддержка любых языков и эмодзи.

На основе предыдущих уроков

  • «Типы данных» — строка как примитивный тип
  • «Преобразование типов» — Number(), String(), parseInt()
  • «Массивы» — split() возвращает массив, join() собирает обратно
  • Создание строк

    const s1 = 'одинарные кавычки'
    const s2 = "двойные кавычки"
    const s3 = `шаблонная строка — поддерживает ${выражения}`
    
    // Многострочные — только шаблонные:
    const html = `
      <div class="card">
        <h2>${title}</h2>
      </div>
    `

    Ключевые методы

    const str = 'Hello, World!'
    
    // Длина и доступ
    str.length           // 13
    str[0]               // 'H'
    str.at(-1)           // '!' — с конца (ES2022)
    
    // Поиск
    str.indexOf('o')     // 4 — первое вхождение (или -1)
    str.lastIndexOf('o') // 8 — последнее
    str.includes('World') // true
    str.startsWith('Hello') // true
    str.endsWith('!')     // true
    
    // Извлечение
    str.slice(7, 12)     // 'World' — от 7 до 12 (не включая)
    str.slice(-6)        // 'orld!' — 6 символов с конца
    
    // Преобразование
    str.toLowerCase()    // 'hello, world!'
    str.toUpperCase()    // 'HELLO, WORLD!'
    str.trim()           // убирает пробелы с обоих краёв
    str.trimStart()      // только с начала
    str.trimEnd()        // только с конца
    
    // Замена
    str.replace('World', 'JS')     // 'Hello, JS!' — первое вхождение
    str.replaceAll('l', 'L')       // 'HeLLo, WorLd!'
    
    // Разбивка / сборка
    'a,b,c'.split(',')             // ['a', 'b', 'c']
    ['a', 'b', 'c'].join(' - ')   // 'a - b - c'
    
    // Дополнение
    '5'.padStart(3, '0')           // '005'
    'hi'.padEnd(5, '.')            // 'hi...'
    
    // Повтор
    'ha'.repeat(3)                 // 'hahaha'

    Шаблонные строки и тегированные шаблоны

    const name  = 'Алексей'
    const price = 1499.99
    
    // Вставка выражений
    const msg = `Привет, ${name}! Ваш заказ на ${price.toFixed(2)} ₽ оформлен.`
    
    // Тернарный оператор внутри
    const status = `Статус: ${isActive ? 'активен' : 'заблокирован'}`
    
    // Вызов метода внутри
    const initials = `${name.split(' ').map(w => w[0]).join('.')}`

    Типичные ошибки

    Ошибка 1: мутация строки

    // Сломано: строки иммутабельны
    let email = 'USER@EXAMPLE.COM'
    email[0] = 'u'              // молча не работает!
    console.log(email[0])       // 'U' — не изменилось
    
    // Исправлено:
    email = email.toLowerCase() // присвоить новую строку

    Ошибка 2: indexOf возвращает -1, а не false

    // Сломано:
    if (str.indexOf('admin')) { ... }  // 0 — тоже falsy! Если 'admin' в начале — не сработает
    
    // Исправлено — используй includes или проверяй !== -1:
    if (str.includes('admin')) { ... }
    if (str.indexOf('admin') !== -1) { ... }

    Ошибка 3: split без аргумента

    // Сломано — разбивает по символам:
    'hello'.split()   // ['hello'] — целая строка как один элемент
    'hello'.split('') // ['h', 'e', 'l', 'l', 'o'] — по символам
    
    // Исправлено:
    'a,b,c'.split(',')  // ['a', 'b', 'c']

    В реальных проектах

  • Нормализация ввода: email.trim().toLowerCase() при регистрации
  • Маскировка данных: card.slice(-4).padStart(16, '*') → '************1234'
  • URL slug: title.toLowerCase().replace(/\s+/g, '-') — ЧПУ из заголовка
  • Шаблоны: строки в HTML-шаблонах, SQL-запросах, email-рассылках
  • Парсинг: line.split(',').map(s => s.trim()) — CSV-файлы
  • Примеры

    Нормализация и форматирование данных пользователя

    // Данные пришли от пользователя — нужна нормализация
    const rawInputs = {
      email:    '  User.Name@EXAMPLE.COM  ',
      fullName: 'иванов   иван   иванович',
      phone:    '8 (916) 123-45-67',
      cardNum:  '4111 1111 1111 1111',
    }
    
    // 1. Email: убрать пробелы, привести к нижнему регистру
    const email = rawInputs.email.trim().toLowerCase()
    console.log(email)   // 'user.name@example.com'
    
    // 2. Имя: нормализовать пробелы, каждое слово с заглавной
    const nameParts = rawInputs.fullName.trim().split(/\s+/)
    const name = nameParts.map(w => w[0].toUpperCase() + w.slice(1)).join(' ')
    console.log(name)    // 'Иванов Иван Иванович'
    
    // 3. Инициалы из имени
    const [lastName, firstName, patronym] = name.split(' ')
    const initials = `${lastName} ${firstName[0]}.${patronym[0]}.`
    console.log(initials)  // 'Иванов И.И.'
    
    // 4. Телефон: только цифры
    const digits = rawInputs.phone.replace(/\D/g, '')
    const phone = '+7 (' + digits.slice(1, 4) + ') ' + digits.slice(4, 7) + '-' + digits.slice(7, 9) + '-' + digits.slice(9)
    console.log(phone)   // '+7 (916) 123-45-67'
    
    // 5. Маскировка карты: показать только последние 4 цифры
    const cardDigits = rawInputs.cardNum.replace(/\s/g, '')
    const masked = cardDigits.slice(-4).padStart(cardDigits.length, '*')
    const formatted = masked.match(/.{4}/g).join(' ')
    console.log(formatted)  // '**** **** **** 1111'
    
    // 6. Генерация username из email
    const username = email.split('@')[0].replace(/[^a-z0-9]/g, '_')
    console.log(username)  // 'user_name'

    Строки

    Реальная проблема: данные из форм и API

    В Telegram при регистрации вы вводите имя — возможно с пробелами по краям, в разном регистре. Ваш код должен нормализовать это, извлечь инициалы, проверить длину, сформатировать отображение. Строки — это хлеб и масло веб-разработчика: почти каждый запрос к API возвращает строки, почти каждая форма отправляет строки.

    Что такое строка в JS

    Строки иммутабельны — нельзя изменить символ по индексу. Каждый метод возвращает новую строку. Строки — Unicode, что значит поддержка любых языков и эмодзи.

    На основе предыдущих уроков

  • «Типы данных» — строка как примитивный тип
  • «Преобразование типов» — Number(), String(), parseInt()
  • «Массивы» — split() возвращает массив, join() собирает обратно
  • Создание строк

    const s1 = 'одинарные кавычки'
    const s2 = "двойные кавычки"
    const s3 = `шаблонная строка — поддерживает ${выражения}`
    
    // Многострочные — только шаблонные:
    const html = `
      <div class="card">
        <h2>${title}</h2>
      </div>
    `

    Ключевые методы

    const str = 'Hello, World!'
    
    // Длина и доступ
    str.length           // 13
    str[0]               // 'H'
    str.at(-1)           // '!' — с конца (ES2022)
    
    // Поиск
    str.indexOf('o')     // 4 — первое вхождение (или -1)
    str.lastIndexOf('o') // 8 — последнее
    str.includes('World') // true
    str.startsWith('Hello') // true
    str.endsWith('!')     // true
    
    // Извлечение
    str.slice(7, 12)     // 'World' — от 7 до 12 (не включая)
    str.slice(-6)        // 'orld!' — 6 символов с конца
    
    // Преобразование
    str.toLowerCase()    // 'hello, world!'
    str.toUpperCase()    // 'HELLO, WORLD!'
    str.trim()           // убирает пробелы с обоих краёв
    str.trimStart()      // только с начала
    str.trimEnd()        // только с конца
    
    // Замена
    str.replace('World', 'JS')     // 'Hello, JS!' — первое вхождение
    str.replaceAll('l', 'L')       // 'HeLLo, WorLd!'
    
    // Разбивка / сборка
    'a,b,c'.split(',')             // ['a', 'b', 'c']
    ['a', 'b', 'c'].join(' - ')   // 'a - b - c'
    
    // Дополнение
    '5'.padStart(3, '0')           // '005'
    'hi'.padEnd(5, '.')            // 'hi...'
    
    // Повтор
    'ha'.repeat(3)                 // 'hahaha'

    Шаблонные строки и тегированные шаблоны

    const name  = 'Алексей'
    const price = 1499.99
    
    // Вставка выражений
    const msg = `Привет, ${name}! Ваш заказ на ${price.toFixed(2)} ₽ оформлен.`
    
    // Тернарный оператор внутри
    const status = `Статус: ${isActive ? 'активен' : 'заблокирован'}`
    
    // Вызов метода внутри
    const initials = `${name.split(' ').map(w => w[0]).join('.')}`

    Типичные ошибки

    Ошибка 1: мутация строки

    // Сломано: строки иммутабельны
    let email = 'USER@EXAMPLE.COM'
    email[0] = 'u'              // молча не работает!
    console.log(email[0])       // 'U' — не изменилось
    
    // Исправлено:
    email = email.toLowerCase() // присвоить новую строку

    Ошибка 2: indexOf возвращает -1, а не false

    // Сломано:
    if (str.indexOf('admin')) { ... }  // 0 — тоже falsy! Если 'admin' в начале — не сработает
    
    // Исправлено — используй includes или проверяй !== -1:
    if (str.includes('admin')) { ... }
    if (str.indexOf('admin') !== -1) { ... }

    Ошибка 3: split без аргумента

    // Сломано — разбивает по символам:
    'hello'.split()   // ['hello'] — целая строка как один элемент
    'hello'.split('') // ['h', 'e', 'l', 'l', 'o'] — по символам
    
    // Исправлено:
    'a,b,c'.split(',')  // ['a', 'b', 'c']

    В реальных проектах

  • Нормализация ввода: email.trim().toLowerCase() при регистрации
  • Маскировка данных: card.slice(-4).padStart(16, '*') → '************1234'
  • URL slug: title.toLowerCase().replace(/\s+/g, '-') — ЧПУ из заголовка
  • Шаблоны: строки в HTML-шаблонах, SQL-запросах, email-рассылках
  • Парсинг: line.split(',').map(s => s.trim()) — CSV-файлы
  • Примеры

    Нормализация и форматирование данных пользователя

    // Данные пришли от пользователя — нужна нормализация
    const rawInputs = {
      email:    '  User.Name@EXAMPLE.COM  ',
      fullName: 'иванов   иван   иванович',
      phone:    '8 (916) 123-45-67',
      cardNum:  '4111 1111 1111 1111',
    }
    
    // 1. Email: убрать пробелы, привести к нижнему регистру
    const email = rawInputs.email.trim().toLowerCase()
    console.log(email)   // 'user.name@example.com'
    
    // 2. Имя: нормализовать пробелы, каждое слово с заглавной
    const nameParts = rawInputs.fullName.trim().split(/\s+/)
    const name = nameParts.map(w => w[0].toUpperCase() + w.slice(1)).join(' ')
    console.log(name)    // 'Иванов Иван Иванович'
    
    // 3. Инициалы из имени
    const [lastName, firstName, patronym] = name.split(' ')
    const initials = `${lastName} ${firstName[0]}.${patronym[0]}.`
    console.log(initials)  // 'Иванов И.И.'
    
    // 4. Телефон: только цифры
    const digits = rawInputs.phone.replace(/\D/g, '')
    const phone = '+7 (' + digits.slice(1, 4) + ') ' + digits.slice(4, 7) + '-' + digits.slice(7, 9) + '-' + digits.slice(9)
    console.log(phone)   // '+7 (916) 123-45-67'
    
    // 5. Маскировка карты: показать только последние 4 цифры
    const cardDigits = rawInputs.cardNum.replace(/\s/g, '')
    const masked = cardDigits.slice(-4).padStart(cardDigits.length, '*')
    const formatted = masked.match(/.{4}/g).join(' ')
    console.log(formatted)  // '**** **** **** 1111'
    
    // 6. Генерация username из email
    const username = email.split('@')[0].replace(/[^a-z0-9]/g, '_')
    console.log(username)  // 'user_name'

    Задание

    Напиши функцию slugify(title), которая превращает заголовок статьи в URL-slug. Правила: привести к нижнему регистру, заменить пробелы и спецсимволы на дефис, убрать повторяющиеся дефисы, убрать дефисы в начале и конце. Например: "Привет, Мир! 2024" → "privet-mir-2024" (используй замену кириллицы или просто работай с латиницей в тесте).

    Подсказка

    Шаг 1: .replace(/[^a-z0-9]+/g, "-"). Шаг 2: .replace(/-+/g, "-"). Шаг 3: .replace(/^-|-$/g, ""). Каждый .replace() возвращает новую строку — вызывай их цепочкой.

    Загружаем среду выполнения...
    Загружаем AI-помощника...