Строки в JS
В JavaScript любые текстовые данные являются строками. Внутренний формат для строк — всегда UTF-16, вне зависимости от кодировки страницы.
Строки в JS обозначаются кавычками:
- одинарными ('Привет');
- двойными ("Привет");
- обратными (для шаблонных литералов):
1 |
`Привет` |
- позволяют вставлять в строку произвольные (вычисляемые) выражения или переменные, обернув их в ${…});
- могут занимать более одной строки (без использования спецсимволов).
1 2 3 4 |
const firstName = 'Alex'; // одинарные const lastName = "NAV"; // двойные const age = 30; const str = `Hello, my name Alex, my age ${age}`; // обратные (// Hello, my name Alex, my age 30 Hello, my name Alex, my age 30) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Использование в строке произвольного выражения function sum(a, b) { return a + b; } alert(`1 + 2 = ${sum(1, 2)}`); // 1 + 2 = 3 // Вывод строки, состоящей из нескольких строк let guestList = `Guests: - John - Pete - Mary `; console.log(guestList); // список гостей, состоящий из нескольких строк |
Шаблонные литералы (строки) в JavaScript
Шаблонными литералами называются строковые литералы, допускающие использование выражений внутри, обозначаемых знаком $ и фигурными скобками (${выражение}). Заключаются в обратные кавычки () (буква "ё"). Позволяют использовать многострочные литералы и строковую интерполяцию.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const firstName = "Alex"; const lastName = "NAV"; const age = 40; let str; // Использование выражений внутри литерала str = `Hello, my name ${firstName} ${lastName}, i'm ${age} years old`; console.log(str); // Пример многострочного литерала str = ` <ul> <li>First name: ${firstName}</li> <li>Last name: ${lastName}</li> <li>Age: ${age}</li> <li>Math.random: ${Math.random().toFixed(2)}</li> </ul> `; document.body.innerHTML = str; |
Спецсимволы в строках JS
Многострочные строки также можно создавать с помощью одинарных и двойных кавычек, используя так называемый «символ перевода строки», который записывается как \n:
1 2 3 4 |
// Вывод строки, состоящей из нескольких строк, с использованием спецсимвола /n let guestList_1 = "Guests:\n * John\n * Pete\n * Mary"; console.log(guestList_1); // список гостей, состоящий из нескольких строк |
Символ | Описание |
\n | Перевод строки |
\r | Возврат каретки: самостоятельно не используется. В текстовых файлах Windows для перевода строки используется комбинация символов \r\n. |
\' , \" | Кавычки (экранированные) |
\\ | Обратный слеш |
\t | Знак табуляции |
\b, \f, \v | Backspace, Form Feed и Vertical Tab — оставлены для обратной совместимости, сейчас не используются. |
\xXX | Символ с шестнадцатеричным юникодным кодом XX, например, '\x7A' — то же самое, что 'z'. |
\uXXXX | Символ в кодировке UTF-16 с шестнадцатеричным кодом XXXX, например, \u00A9 — юникодное представление знака копирайта, ©. Код должен состоять ровно из 4 шестнадцатеричных цифр. |
\u{X…XXXXXX} (от 1 до 6 шестнадцатеричных цифр) | Символ в кодировке UTF-32 с шестнадцатеричным кодом от U+0000 до U+10FFFF. Некоторые редкие символы кодируются двумя 16-битными словами и занимают 4 байта. Так можно вставлять символы с длинным кодом. |
Особенности экранирования кавычек обратным слэшем (\):
- требование экранировать относится только к таким же кавычкам, как те, в которые заключена строка.
1 2 3 4 5 6 7 |
// Перед входящей в строку кавычкой необходимо добавить обратный слеш — \', иначе она бы обозначала окончание строки. alert( 'I\'m Alex!' ); // I'm Alex! // Более элегантное решение - использование обратных кавычек: alert( `I'm Alex!` ); // I'm Alex! |
Свойства строки JS
Свойство length (длина строки)
Свойство length содержит длину строки:
1 2 3 4 5 |
const firstName = "Alex"; const lastName = "NAV"; let value = firstName + " " + lastName; // 'Alex NAV' value = value.length; // 8 (длина строки посимвольно, с пробелами) alert( `My\n`.length ); // 3 (длина строки посимвольно, с учетом спецсимвола \n) |
Так как length— это числовое свойство, а не функция, то добавлять скобки не нужно.
Свойство length строки можно использовать для проверки строки на пустоту (empty string): str.length===0.
Конкатенация строк в JavaScript
Конкатенация (объединение) строк в JS возможно двумя способами:
- с использованием оператора "+";
- с использованием метода concat.
1 2 3 4 5 6 7 8 9 10 |
const firstName = "Alex"; const lastName = "NAV"; const age = 30; let value; value = firstName + " " + lastName; // Alex NAV (конкатенация бинарным "+") value += " My age " + age; // Alex NAV My age 30 (конкатенация бинарным "+") value = lastName.concat(" ", firstName); // NAV Alex (конкатенация методом concat) |
Методы строки JS
Получение символа строки JS (метод charAt())
Получить символ строки на нужной позиции pos, можно:
- с помощью квадратных скобок: [pos];
- методом charAt(pos) (устаревший способ).
1 2 3 4 5 6 7 8 9 |
const firstName = "Alex"; let value; value = firstName[5]; // undefined (т.к. длина имени 4 символа) value = firstName[3]; // x (4-й символ, т.к. нумерация с 0) // Получение последнего символа в строке (нумерация с 0!) value = firstName.length; // длина строки посимвольно, с пробелами value = firstName[firstName.length - 1]; // x (последний символ строки) |
Также можно использовать метод charAt(pos). Первый символ занимает нулевую позицию:
1 2 |
value = firstName.charAt(0); // первый символ value = firstName.charAt(2); // третий символ |
Отличие [pos] от charAt(pos):
- если символ на позиции pos отсутствует, тогда
- [pos] вернёт undefined;
- charAt(pos) вернёт пустую строку:
Изменение регистра символов строки JS (методы toLowerCase() и toUpperCase())
Методы toLowerCase() и toUpperCase() меняют регистр символов:
1 2 3 4 |
const firstName = "Alex"; let value; value = firstName.toUpperCase(); // ALEX (все символы строки) value = firstName[3].toUpperCase(); // X (4-й символ, т.к. нумерация с 0) |
ВАЖНО! Строки неизменяемы. Содержимое строки в JavaScript нельзя изменить, т.е. нельзя взять символ посередине строки и заменить его. Её можно изменить лишь перезаписав в ту же переменную.
Метод split() разбивает объект String на массив строк путём разделения строки указанной подстрокой.
1 |
str.split([separator[, limit]]) |
Параметры метода split():
- separator (необязательный) - указывает символы, используемые в качестве разделителя внутри строки. Параметр separator может быть как строкой, так и регулярным выражением:
- если разделитель separator найден, он удаляется из строки, а подстроки возвращаются в массиве;
- если параметр опущен, возвращённый массив будет содержать один элемент со всей строкой;
- если параметр равен пустой строке, строка str будет преобразована в массив символов.
- limit (необязательный) - целое число, определяющее ограничение на количество найденных подстрок. Метод split() всё равно разделяет строку на каждом сопоставлении с разделителем separator, но обрезает возвращаемый массив так, чтобы он содержал не более limit элементов.
Если разделитель является регулярным выражением, содержащим подгруппы, то каждый раз при сопоставлении с разделителем, результаты (включая те, что не определены) захвата подгруппы будут помещаться внутрь выходного массива. Однако не все браузеры поддерживают эту возможность.
Если строка является пустой строкой, метод split() вернёт массив, состоящий из одной пустой строки, а не пустой массив.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
let names = "Alex, Olga, Serg, Mary"; let arrNames = names.split(", "); console.log(arrNames); // Array(4) [ "Alex", "Olga", "Serg", "Mary" ] let resName = "Сообщение получат: "; for (let name of arrNames) { resName += name + ", "; } console.log(resName); // Сообщение получат: Alex, Olga, Serg, Mary, let arrName = "Alex, Olga, Serg, Mary".split(", ", 2); console.log(arrName); // Array [ "Alex", "Olga" ] |
Реверс строки в JavaScript:
1 2 3 4 5 6 7 |
function newReverseString(str) { return str .split("") .reverse() .join(""); } console.log(newReverseString("test")); // tset |
Про reverse() и join() смотри Массивы в JavaScript
Поиск подстроки в JavaScript
Существует несколько способов поиска подстроки:
- метод indexOf(substr[, pos]) - ищет подстроку substr в строке str, начиная с позиции pos (необязательный аргумент), и возвращает:
- позицию, на которой располагается совпадение, либо
- -1 (при отсутствии совпадений);
- метод lastIndexOf(substr[, pos]) - ищет подстроку с конца строки к её началу (ищет справа налев, а номер позиции отсчитывается слева направо) и используется тогда, когда нужно получить самое последнее вхождение: перед концом строки или начинающееся до (включительно) определённой позиции.
- с использованием побитового оператора НЕ — ~.
1 2 3 4 5 |
const str = `Hello, my name Alex, my age ${age}`; let value; value = str.indexOf("name"); // 10 (возвращает номер позиции первого вхождения подстроки в строку str) value = str.indexOf("A", 10); // 15 (возвращает номер позиции первого вхождения подстроки в строку str, начиная с указанной позиции)) |
Чтобы найти все вхождения подстроки, нужно запустить indexOf в цикле. Каждый раз, получив очередную позицию, начинаем новый поиск со следующей.
1 2 3 4 5 6 7 8 9 10 |
let str = 'Ослик Иа-Иа посмотрел на виадук'; // строка, в которой будем искать let target = 'Иа'; // подстрока поиска let pos = 0; // задаем начальную позицию поиска while (true) { let foundPos = str.indexOf(target, pos); if (foundPos == -1) break; alert( `Найдено тут: ${foundPos}` ); pos = foundPos + 1; // продолжаем поиск со следующей позиции } |
Тот же алгоритм можно записать и короче:
1 2 3 4 5 6 |
let str = "Ослик Иа-Иа посмотрел на виадук"; let target = "Иа"; let pos = -1; while ((pos = str.indexOf(target, pos + 1)) != -1) { alert( pos ); } |
При проверке indexOf в условии if есть небольшой нюанс. Такое условие не будет работать:
1 2 3 4 |
let str = "Widget with id"; if (str.indexOf("Widget")) { alert("Совпадение есть"); // не работает } |
Мы ищем подстроку "Widget", и она здесь есть, прямо на позиции 0. Но alert не показывается, т. к. str.indexOf("Widget") возвращает 0 (false), и if решает, что тест не пройден.
Поэтому надо делать проверку на -1:
1 2 3 4 |
let str = "Widget with id"; if (str.indexOf("Widget") != -1) { alert("Совпадение есть"); // теперь работает } |
Побитовый оператор НЕ (~) преобразует число в 32-разрядное целое со знаком (signed 32-bit integer). Дробная часть, в случае, если она присутствует, отбрасывается. Затем все биты числа инвертируются.
На практике это означает простую вещь: для 32-разрядных целых чисел значение ~n равно -(n+1).
В частности:
1 2 3 4 |
alert( ~2 ); // -3, то же, что -(2+1) alert( ~1 ); // -2, то же, что -(1+1) alert( ~0 ); // -1, то же, что -(0+1) alert( ~-1 ); // 0, то же, что -(-1+1) |
Таким образом, ~n равняется 0 только при n == -1 (для любого n, входящего в 32-разрядные целые числа со знаком).
Соответственно, прохождение проверки if ( ~str.indexOf("…") ) означает, что результат indexOf отличен от -1, совпадение есть.
Это иногда применяют, чтобы сделать проверку indexOf компактнее:
1 2 3 4 |
let str = "Widget"; if (~str.indexOf("Widget")) { alert( 'Совпадение есть' ); // работает } |
Использовать возможности языка таким неочевидным образом не рекомендуется (но могло быть использовано в старом коде).
Просто запомните: if (~str.indexOf(…)) означает «если найдено».
Проверка наличия подстроки в строке (методы includes, startsWith, endsWith)
Метод includes(substr[, pos]) используется при проверке строки на совпадение, при том что позиция не нужна (возвращает true, если в строке str есть подстрока substr, либо false, если нет).
1 2 3 4 |
const str = `Hello, my name Alex, my age ${age}`; let value; value = str.includes("name"); // true value = str.includes("you"); // false |
Необязательный второй аргумент pos позволяет начать поиск с определённой позиции/
Методы startsWith и endsWith проверяют, соответственно, начинается ли и заканчивается ли строка определённой подстрокой:
1 2 3 4 |
const str = `Hello, my name Alex, my age ${age}`; let value; value = str.startsWith("name"); // false value = str.startsWith("Hell"); // true |
Получение подстроки в JavaScript (методы substring и slice)
В JavaScript есть 3 метода для получения подстроки:
- slice(start [, end])- возвращает часть строки от start до (не включая) end (поддерживает отрицательные значения аргументов).
- substring(start [, end]) - возвращает часть строки между start и end (можно задавать start больше end, отрицательные значения аргументов не поддерживает).
- substr(start [, length]) - (устаревший) возвращает часть строки от start длины length (позволяет указать длину подстроки вместо конечной позиции).
1 2 3 4 5 6 7 8 9 10 11 |
const str = `Hello, my name Alex, my age ${age}`; let value; value=str.slice(10,15) // name value=str.slice(-10,-5) // my a (поддерживает отрицательные значения, начинаем с 10-й позиции справа, отсчитываем 5 символов влево) value=str.substring(0,7) // Hello, value=str.substring(10,7) // my value=str.substr(10,15) // name Alex, my a |
Внимание: так как String.prototype.substr(…) не полностью упразднен (а лишь "удален из стандартов по вебу"), он считается унаследованной функцией, использование которой лучше избегать там, где это возможно. Он не является частью ядра языка JavaScript и может быть удален в будущем. Если есть возможность, используйте метод substring().
Замена части строки (метод replace)
Метод поиска и замены replace() возвращает новую строку с заменёнными на заменитель некоторыми или всеми совпадениями с шаблоном. Шаблон может быть строкой или регулярным выражением, а заменитель может быть строкой или функцией, вызываемой при каждом сопоставлении.
Замечание: когда первый аргумент replace является строкой, он заменяет только первое совпадение. Для того чтобы найти все совпадения и заменить их, необходимо использовать регулярное выражение с обязательным флагом g.
1 |
str.replace(regexp|substr, newSubStr|function[, flags]) |
где
- regexp - объект регулярного выражения RegExp(); сопоставление заменяется возвращаемым значением второго параметра;
- substr - строка, заменяемая на newSubStr (будет заменено только первое вхождение искомой строки);
- newSubStr - строка, заменяющая подстроку из первого параметра; поддерживает несколько специальных шаблонов замены;
- function - функция, вызываемая для создания новой подстроки (помещаемой вместо подстроки из первого параметра);
- flags - строка, задающая комбинацию флагов регулярного выражения; внимание: аргумент flags не работает в ядре v8 (движок JavaScript в Chrome и NodeJs).
Параметр flags в методе String.prototype.replace() является нестандартным расширением. Вместо использования этого параметра используйте объект RegExp с соответствующими флагами.
Можно ещё почитать https://habr.com
По регулярным выражениям https://mattweb.ru
Спецсимволы | Действие в строке замены |
$$ | вставляет "$" |
$& | вставляет найденное совпадение (шаблон) |
$` | вставляет предыдущую часть строки (до совпадения) |
$' | вставляет оставшуюся (после совпадения) часть строки |
$n | если n это 1(2)-значное число, то вставляет содержимое n-й скобки (при использовании регулярных выражений) |
$<имя> | вставляет содержимое скобки с указанным именем |
1 2 3 4 5 6 |
const age = 30; const str = `Hello, my name Alex, my age ${age}`; let value; value = str.replace("Alex", "Olga") console.log(value); // Hello, my name Olga, my age 30 |
1 2 3 4 5 6 7 8 9 10 |
let myString = "Здравствуйте, я - ваша тетя!"; let value = myString.replace("ваша тетя", "ваш дядя"); // Здравствуйте, я - ваш дядя! value = myString.replace("ваша тетя"); // Здравствуйте, я - undefined! value = myString.replace("ваша тетя", "$$"); // Здравствуйте, я - $! value = myString.replace("ваша тетя", "$'"); // Здравствуйте, я - !! (вставляет оставшуюся (после совпадения) часть строки) value = myString.replace("ваша тетя", "$`"); // Здравствуйте, я - Здравствуйте, я - ! ( вставляет предыдущую часть строки (до совпадения) regEx = /([а-яё]+)\s([а-яё]+)/i; value = myString.replace(regEx, "$2, $1"); // Здравствуйте, я - тетя, ваша! (с использованием регулярного выражения) |
Удаление пробелов в строке JS
Метод str.trim() — убирает пробелы в начале и конце строки.
Повтор строки JS
Метод str.repeat(n) — повторяет строку n раз.
Сравнение строк в JavaScript
Строки в JS сравниваются посимвольно в алфавитном порядке.
Особенности посимвольного сравнения строк в JS:
- Символы сравниваются по их кодам (больший код — больший символ, все строчные буквы идут после (правее) заглавных, так как их коды больше ('a' > 'Z' // 97>65 true) ;
- Буквы, имеющие диакритические знаки, идут «не по порядку» ( 'Österreich' > 'Zealand' );
Для получения символа по его коду (и наоборот) используется методы:
- codePointAt(pos), который возвращает код Unicode для символа, находящегося на позиции pos;
- charCodeAt(pos), который возвращает числовое значение Unicode UTF-16 для символа по указанному индексу (за исключением кодовых точек Unicode, больших 0x10000).
- String.fromCodePoint(code) - создаёт символ по его коду code
1 2 3 4 5 6 7 8 9 |
// одна и та же буква в нижнем и верхнем регистре будет иметь разные коды alert( "z".codePointAt(0) ); // 122 alert( "Z".codePointAt(0) ); // 90 // Создание символа по его коду code alert( String.fromCodePoint(90) ); // Z // Добавление юникодного символа по коду, используя спецсимвол \u alert( '\u005a' ); // Z |
Выведем строку, содержащую символы с кодами от 65 до 90 — это латиница (символы заглавных букв):
1 2 3 4 5 6 |
let str_1 = ""; for (let i = 65; i <= 90; i++) { str_1 += String.fromCodePoint(i); } console.log(str_1); // ABCDEFGHIJKLMNOPQRSTUVWXYZ |
Правильное сравнение строк (метод str1.localeCompare(str2))
Вызов метода str1.localeCompare(str2) возвращает число, которое показывает, какая строка больше в соответствии с правилами языка:
- Отрицательное число, если str1 меньше str2.
- Положительное число, если str1 больше str2.
- 0, если строки равны.
1 2 3 4 |
let str_1 = 'Alex'.localeCompare('NAV'); console.log(str_1); // -1 let str_2 = 'Alex'.localeCompare('Alex'); console.log(str_2); // 0 |
Примеры операций со строками JS
Посимвольный перебор строки
1 2 3 |
for (let char of "Hello") { alert(char); // H,e,l,l,o (char — сначала "H", потом "e", потом "l" и т. д.) } |
Получить первую и последнюю буквы строки
1 2 |
console.log(string[0]); // первая буква console.log(string[string.length - 1]); // последняя буква |
Сделать первую и последнюю буквы строки в верхнем регистре
1 2 3 4 5 6 7 8 |
string = string[0].toUpperCase() + string.slice(1, -1) + string[string.length - 1].toUpperCase(); // или string = `${string[0].toUpperCase()}${string.slice(1, -1)}${string[ string.length - 1].toUpperCase()}`; |
Найти положение слова в строке
1 |
value = string.indexOf("string"); |
Найти положение второго пробела
1 2 3 |
let value_1 = string.indexOf(" "); // позиция первого пробела let value_2 = string.indexOf(" ", value_1 + 1); // позиция второго пробела console.log(value_2); |
Получить строку с i-го символа длиной n букв
1 2 |
value = string.substr(i, n); console.log(value); |
Получить строку с i-го по n-й символы
1 2 |
value = string.slice(i, n+1); // т.к. по n-й символ, аргумент (n+1) (он в выборку не включается) console.log(value); |
Удаление из строки последних n символов
1 2 3 4 |
value = string.slice(0, -6); // т.к. метод slice поддерживает отрицательные значения // или value = string.slice(0, string.length - 6); |
Получение строки из переменных
1 2 3 4 5 6 7 8 9 |
let a = 20; let b = 16; let string = a.toString()+b.toString(); // Или let string = String(a)+String(b); // Или let string = a + "" + b; console.log(string, typeof string); // 2016 string |