⚡ JavaScript

Методы строк — полное руководство в JavaScript (Node.js): подробное руководство

Что это такое и зачем? (аналогия из реальной жизни)

Представьте, что вы получили длинное письмо от друга. В нём много текста: приветствие, новости, вопросы, прощание. Что вы можете с ним сделать? Вы можете:

  • Прочитать его целиком или отдельные части (например, только первый абзац).
  • Найти в нём конкретное слово (например, «встреча»).
  • Заменить одно слово на другое (например, «понедельник» на «вторник»).
  • Разделить письмо на предложения или слова.
  • Проверить, с какого слова оно начинается и заканчивается.
  • Посчитать, сколько в нём букв, пробелов или восклицательных знаков.

В программировании строка (string) — это точно такое же «письмо». Это последовательность символов: букв, цифр, пробелов, знаков препинания. А методы строк — это готовые инструменты (как ножницы, лупа, линейка), которые JavaScript даёт нам для работы с этим текстом. Вам не нужно изобретать велосипед: всё уже написано за вас.

💡 Важно: Строки в JavaScript — это примитивный тип данных. Это значит, что они хранятся как простые значения, а не как сложные объекты. Но при вызове методов JavaScript временно «оборачивает» строку в объект, чтобы вы могли пользоваться всеми этими удобными функциями.

Зачем это нужно? Представьте, что вы пишете программу, которая проверяет пароль: содержит ли он заглавные буквы, цифры и специальные символы. Или вы делаете поиск по сайту и нужно выделить найденные слова. Или вы обрабатываете данные из файла: убираете лишние пробелы, приводите всё к нижнему регистру. Без методов строк вам пришлось бы писать десятки строк кода для каждой такой операции. С методами — это одна строчка.

Теория: как это работает изнутри

Давайте заглянем «под капот». Когда вы пишете:

let text = "Привет, мир!";
console.log(text.length); // 12

JavaScript считает каждый символ. Пробел — тоже символ. Восклицательный знак — символ. Каждая буква — символ. length — это не метод, а свойство. Оно просто хранит число — длину строки.

А вот toUpperCase() — это уже метод. Когда вы его вызываете:

let bigText = text.toUpperCase();

Происходит следующее:

  1. JavaScript берёт исходную строку "Привет, мир!".
  2. Создаёт новую строку, где каждая буква заменена на заглавную: "ПРИВЕТ, МИР!".
  3. Возвращает эту новую строку.
  4. Исходная строка text остаётся без изменений.
⚠️ Ключевой момент: Строки в JavaScript неизменяемы (immutable). Это значит, что вы не можете изменить существующую строку. Вы всегда создаёте новую. Методы строк никогда не меняют оригинал, они возвращают новый результат.

Почему это важно? Потому что если вы напишете:

let name = "Иван";
name.toUpperCase();
console.log(name); // "Иван" — не изменилось!

Чтобы сохранить результат, нужно присвоить его переменной:

let name = "Иван";
let upperName = name.toUpperCase();
console.log(upperName); // "ИВАН"

Теперь разберёмся с индексами. Каждый символ в строке имеет свой номер (индекс), начиная с нуля:

let word = "Кот";
// Индексы: 0: 'К', 1: 'о', 2: 'т'

Многие методы строк используют эти индексы. Например, charAt(1) вернёт символ с индексом 1 — это 'о'. А slice(0, 2) вернёт подстроку с индекса 0 по индекс 2 (не включая его) — это "Ко".

Методы можно цепочкой вызывать один за другим, потому что каждый метод возвращает новую строку:

let result = "  Привет, Мир!  ".trim().toLowerCase().replace("мир", "все");
// Результат: "привет, все!"

Здесь trim() убрал пробелы, toLowerCase() сделал все буквы маленькими, а replace() заменил слово. Каждый метод работает с результатом предыдущего.

Синтаксис в JavaScript (Node.js): все формы и варианты

В JavaScript (и Node.js) строки можно создавать тремя способами:

// 1. Одинарные кавычки
let str1 = 'Привет';

// 2. Двойные кавычки
let str2 = "Привет";

// 3. Обратные кавычки (шаблонные строки) — самые мощные
let name = "Анна";
let str3 = `Привет, ${name}!`; // "Привет, Анна!"

Шаблонные строки (backticks) позволяют вставлять переменные прямо в текст с помощью ${} и писать многострочный текст без .

Теперь — полный справочник методов. Я разделил их на группы по назначению.

Таблица 1: Методы для изменения регистра и удаления пробелов

Метод Что делает Пример Результат
toUpperCase() Превращает все буквы в заглавные "кот".toUpperCase() "КОТ"
toLowerCase() Превращает все буквы в строчные "КоТ".toLowerCase() "кот"
trim() Убирает пробелы в начале и конце " да ".trim() "да"
trimStart() Убирает пробелы только в начале " да".trimStart() "да"
trimEnd() Убирает пробелы только в конце "да ".trimEnd() "да"

Таблица 2: Методы для поиска и проверки

Метод Что делает Пример Результат
includes(подстрока) Проверяет, есть ли подстрока внутри "Привет".includes("рив") true
startsWith(подстрока) Проверяет, начинается ли строка с подстроки "Привет".startsWith("При") true
endsWith(подстрока) Проверяет, заканчивается ли строка на подстроку "Привет".endsWith("вет") true
indexOf(подстрока) Ищет первое вхождение, возвращает индекс или -1 "Кот и кот".indexOf("кот") 6
lastIndexOf(подстрока) Ищет последнее вхождение, возвращает индекс или -1 "Кот и кот".lastIndexOf("кот") 6
search(регулярка) Ищет по регулярному выражению, возвращает индекс "Кот123".search(/d+/) 3

Таблица 3: Методы для извлечения части строки

Метод Что делает Пример Результат
slice(начало, конец) Извлекает часть от начала до конца (не включая конец) "Привет".slice(0, 4) "Прив"
substring(начало, конец) Похож на slice, но не поддерживает отрицательные индексы "Привет".substring(0, 4) "Прив"
substr(начало, длина) Извлекает указанное количество символов (устаревший) "Привет".substr(0, 4) "Прив"
charAt(индекс) Возвращает символ по индексу "Привет".charAt(2) "и"
at(индекс) Современный аналог charAt, поддерживает отрицательные "Привет".at(-1) "т"

Таблица 4: Методы для замены и разделения

Метод Что делает Пример Результат
replace(что, на_что) Заменяет первое вхождение "кот кот".replace("кот", "пёс") "пёс кот"
replaceAll(что, на_что) Заменяет все вхождения "кот кот".replaceAll("кот", "пёс") "пёс пёс"
split(разделитель) Разбивает строку на массив по разделителю "а,б,в".split(",") ["а", "б", "в"]
concat(строка1, строка2, ...) Объединяет строки (можно просто +) "а".concat("б", "в") "абв"
repeat(количество) Повторяет строку n раз "ха".repeat(3) "хахаха"

Таблица 5: Дополнительные полезные методы

Метод Что делает Пример Результат
padStart(длина, символ) Дополняет строку слева до нужной длины "5".padStart(3, "0") "005"
padEnd(длина, символ) Дополняет строку справа до нужной длины "5".padEnd(3, "0") "500"
match(регулярка) Ищет совпадения по регулярному выражению "a1b2".match(/d/g) ["1", "2"]
localeCompare(другая) Сравнивает строки с учётом локали (для сортировки) "а".localeCompare("б") -1

Примеры кода — от простого к сложному

Пример 1: Приветствие с проверкой имени

// Простейший пример: проверяем, что имя не пустое и не содержит цифр
let userName = "  Анна  ";

// Убираем лишние пробелы
let cleanedName = userName.trim();

// Проверяем, начинается ли имя с заглавной буквы
let isCapitalized = cleanedName[0] === cleanedName[0].toUpperCase();

// Выводим результат
console.log(`Привет, ${cleanedName}!`);
console.log(`Имя начинается с заглавной: ${isCapitalized}`);

// Объяснение:
// 1. trim() убирает пробелы в начале и конце
// 2. cleanedName[0] — берём первый символ (индекс 0)
// 3. Сравниваем его с его же заглавной версией
// Результат: "Привет, Анна!" и "Имя начинается с заглавной: true"

Пример 2: Поиск и замена в тексте

let text = "JavaScript — это круто! Я люблю JavaScript.";

// Проверяем, есть ли слово "круто"
let hasCool = text.includes("круто");
console.log(`Слово "круто" найдено: ${hasCool}`); // true

// Заменяем первое вхождение "JavaScript" на "JS"
let replacedOnce = text.replace("JavaScript", "JS");
console.log("После одной замены:", replacedOnce);
// "JS — это круто! Я люблю JavaScript."

// Заменяем все вхождения "JavaScript" на "JS"
let replacedAll = text.replaceAll("JavaScript", "JS");
console.log("После всех замен:", replacedAll);
// "JS — это круто! Я люблю JS."

// Объяснение:
// 1. includes() возвращает true/false
// 2. replace() меняет только первое совпадение
// 3. replaceAll() меняет все совпадения (появился в ES2021)

Пример 3: Разделение строки на части

let csvData = "Иван,25,Москва,программист";

// Разбиваем строку по запятой на массив
let parts = csvData.split(",");

console.log("Массив данных:", parts);
// ["Иван", "25", "Москва", "программист"]

// Теперь можем обращаться к каждому элементу
let name = parts[0];
let age = parts[1];
let city = parts[2];
let job = parts[3];

console.log(`Имя: ${name}, Возраст: ${age}, Город: ${city}, Профессия: ${job}`);

// Обратный процесс: собираем массив обратно в строку
let newCsv = parts.join("; ");
console.log("Новая строка:", newCsv);
// "Иван; 25; Москва; программист"

// Объяснение:
// 1. split(",") — режет строку по запятым
// 2. Получаем массив из 4 элементов
// 3. join("; ") — склеивает массив обратно, но уже с точкой с запятой

Пример 4: Валидация email-адреса

function validateEmail(email) {
    // Убираем пробелы
    let cleanEmail = email.trim().toLowerCase();
    
    // Проверяем, есть ли символ @
    if (!cleanEmail.includes("@")) {
        return "Ошибка: email должен содержать @";
    }
    
    // Разбиваем на локальную часть и домен
    let parts = cleanEmail.split("@");
    
    // Должно быть ровно 2 части
    if (parts.length !== 2) {
        return "Ошибка: слишком много символов @";
    }
    
    let localPart = parts[0];
    let domain = parts[1];
    
    // Проверяем, что локальная часть не пустая
    if (localPart.length === 0) {
        return "Ошибка: нет имени перед @";
    }
    
    // Проверяем, что домен содержит точку
    if (!domain.includes(".")) {
        return "Ошибка: домен должен содержать точку";
    }
    
    // Проверяем, что домен заканчивается на допустимую зону
    let validEndings = [".com", ".ru", ".org", ".net"];
    let hasValidEnding = validEndings.some(ending => domain.endsWith(ending));
    
    if (!hasValidEnding) {
        return "Ошибка: неизвестная доменная зона";
    }
    
    return "Email корректен!";
}

// Тестируем
console.log(validateEmail("  Test@Example.COM  ")); // Email корректен!
console.log(validateEmail("invalid-email"));        // Ошибка: email должен содержать @
console.log(validateEmail("@domain.com"));          // Ошибка: нет имени перед @
console.log(validateEmail("test@domain"));          // Ошибка: домен должен содержать точку

// Объяснение:
// 1. trim() и toLowerCase() — очищаем и нормализуем
// 2. includes() — проверяем наличие @
// 3. split("@") — делим на части
// 4. endsWith() — проверяем окончание домена
// 5. some() — метод массива, проверяет хотя бы одно совпадение

Пример 5: Форматирование номера телефона

function formatPhone(phone) {
    // Убираем всё, кроме цифр
    let digits = phone.replace(/D/g, "");
    // D — не цифра, g — все вхождения
    
    console.log("Только цифры:", digits);
    
    // Проверяем длину
    if (digits.length !== 11) {
        return "Ошибка: номер должен содержать 11 цифр";
    }
    
    // Форматируем: +7 (XXX) XXX-XX-XX
    let countryCode = digits[0]; // первая цифра
    let areaCode = digits.slice(1, 4); // три цифры
    let firstPart = digits.slice(4, 7); // три цифры
    let secondPart = digits.slice(7, 9); // две цифры
    let thirdPart = digits.slice(9, 11); // две цифры
    
    let formatted = `+${countryCode} (${areaCode}) ${firstPart}-${secondPart}-${thirdPart}`;
    
    return formatted;
}

// Тестируем
console.log(formatPhone("+7 123 456 78 90")); // +7 (123) 456-78-90
console.log(formatPhone("81234567890"));       // +8 (123) 456-78-90
console.log(formatPhone("12345"));             // Ошибка: номер должен содержать 11 цифр

// Объяснение:
// 1. replace(/D/g, "") — регулярка убирает всё, кроме цифр
// 2. slice() — вырезаем части строки по индексам
// 3. Шаблонная строка с ${} собирает всё в красивый формат

Пример 6: Анализ текста (счётчик слов и символов)

function analyzeText(text) {
    if (text.trim().length === 0) {
        return "Текст пустой!";
    }
    
    // Убираем лишние пробелы
    let cleanText = text.trim();
    
    // Считаем символы
    let charCount = cleanText.length;
    
    // Считаем символы без пробелов
    let charCountNoSpaces = cleanText.replace(/s/g, "").length;
    
    // Разбиваем на слова (по пробелам)
    let words = cleanText.split(/s+/);
    let wordCount = words.length;
    
    // Считаем предложения (по точке, восклицательному и вопросительному знаку)
    let sentences = cleanText.split(/[.!?]+/).filter(s => s.length > 0);
    let sentenceCount = sentences.length;
    
    // Находим самое длинное слово
    let longestWord = words.reduce((longest, current) => {
        return current.length > longest.length ? current : longest;
    }, "");
    
    return {
        символы: charCount,
        символы_без_пробелов: charCountNoSpaces,
        слова: wordCount,
        предложения: sentenceCount,
        самое_длинное_слово: longestWord
    };
}

let result = analyzeText("Привет, мир! Как дела? Всё отлично.");
console.log("Анализ текста:", result);
// {
//   символы: 38,
//   символы_без_пробелов: 31,
//   слова: 6,
//   предложения: 3,
//   самое_длинное_слово: "отлично"
// }

// Объяснение:
// 1. trim() — убираем пробелы по краям
// 2. replace(/s/g, "") — убираем все пробелы внутри
// 3. split(/s+/) — делим по одному или нескольким пробелам
// 4. split(/[.!?]+/) — делим по знакам конца предложения
// 5. filter() — убираем пустые строки из массива
// 6. reduce() — находим самое длинное слово перебором

Пример 7: Шифр Цезаря (сдвиг букв)

function caesarCipher(text, shift) {
    let result = "";
    
    for (let i = 0; i < text.length; i++) {
        let char = text[i];
        
        // Проверяем, является ли символ буквой
        if (char.match(/[a-zA-Zа-яА-Я]/)) {
            // Определяем, заглавная ли буква
            let isUpperCase = char === char.toUpperCase();
            
            // Приводим к нижнему регистру для расчёта
            let lowerChar = char.toLowerCase();
            
            // Получаем код символа (число)
            let charCode = lowerChar.charCodeAt(0);
            
            // Определяем базу (код 'а' или 'a')
            let base = (lowerChar >= 'а' && lowerChar <= 'я') ? 'а'.charCodeAt(0) : 'a'.charCodeAt(0);
            
            // Сдвигаем и зацикливаем
            let newCode = ((charCode - base + shift) % 26 + 26) % 26 + base;
            
            // Преобразуем обратно в символ
            let newChar = String.fromCharCode(newCode);
            
            // Если была заглавная — делаем заглавной
            result += isUpperCase ? newChar.toUpperCase() : newChar;
        } else {
            // Не буквы оставляем как есть
            result += char;
        }
    }
    
    return result;
}

let original = "Привет, Мир!";
let encrypted = caesarCipher(original, 3);
let decrypted = caesarCipher(encrypted, -3);

console.log("Оригинал:", original);   // "Привет, Мир!"
console.log("Зашифровано:", encrypted); // "Тулезх, Плу!"
console.log("Расшифровано:", decrypted); // "Привет, Мир!"

// Объяснение:
// 1. Проходим по каждому символу циклом
// 2. match(/[a-zA-Zа-яА-Я]/) — проверяем, буква ли это
// 3. charCodeAt(0) — получаем числовой код символа (Unicode)
// 4. Вычисляем сдвиг с зацикливанием через модуль (%)
// 5. String.fromCharCode() — превращаем код обратно в символ
// 6. Сохраняем регистр исходной буквы

Сравнение с Python: чем похоже и чем отличается

Если вы уже знаете Python или планируете его учить, вот ключевые различия и сходства в работе со строками:

Операция JavaScript Python Примечание
Длина строки "текст".length len("текст") В JS это свойство, в Python — функция
Индексация "текст"[0] "текст"[0] Оба поддерживают, но в Python можно "текст"[-1] (с конца)
Срезы (slice) "текст".slice(1, 3) "текст"[1:3] В Python синтаксис короче и мощнее (шаг, отрицательные индексы)
Поиск подстроки "текст".includes("екс") "екс" in "текст" Python использует оператор in
Замена "текст".replace("екс", "est") "текст".replace("екс", "est") Почти одинаково, но в Python replace меняет все вхождения по умолчанию
Разделение "а,б,в".split(",") "а,б,в".split(",") Идентично
Объединение ["а","б"].join(",") ",".join(["а","б"]) Синтаксис перевёрнут: в JS метод массива, в Python — метод строки
Регистр toUpperCase(), toLowerCase() upper(), lower() Почти одинаково, только названия чуть короче в Python
Проверка начала/конца startsWith(), endsWith() startswith(), endswith() В Python с маленькой буквы и без CamelCase
Удаление пробелов trim(), trimStart(), trimEnd() strip(), lstrip(), rstrip() Разные названия, но логика та же
Форматирование `Привет, ${name}!` f"Привет, {name}!" Очень похожий синтаксис с f-строками
Неизменяемость Да, строки immutable Да, строки immutable