Методы и свойства строк

По аналогии с числами у строк тоже есть свой набор методов, упрощающих работу с ними. И, как вы уже догадались, на этом занятии мы будем рассматривать методы работы со строками. Но в начале отметим, что все строки в JavaScript представлены в кодировке UTF-16, даже если в браузере HTML-документ имеет другую кодировку.

Итак, поехали. Мы с вами уже говорили о разнообразии кавычек для представления строковых литералов, например:

let str1 = "Hello World!";
let str2 = 'Hello World!';
let str3 = `Hello World!`;

Все это одинаковые строки, то есть, кавычки «работают» одинаково, но последние предоставляют нам более широкий функционал и позволяют вписывать значения переменных непосредственно в строку:

let name = "Java", age = 18;
let str = `Меня зовут ${name}, мне ${age} лет`;
console.log( str );

Обо всем это мы с вами уже говорили. Продолжим. В строках можно указывать специальные управляющие символы (они называются спецсимволами). Наиболее распространенных несколько:

  • \n – спецсимвол перевода на новую строку;
  • \r – возврат каретки (используется в ОС Windows совместно с символом \n);
  • \t – спецсимвол табуляции;
  • \uXXXX – символ в кодировке UTF-16;
  • \" и \' – символы кавычек (внутри строки);
  • \\ - символ обратного слеша.

Существуют и другие спецсимволы, но они используются довольно редко. Вот примеры использования этих символов:

let str = 'Hello!\nI\'m Javascript.\nВот мой символ \t табуляции, обратный слеш \\ и символ \u00A9 копирайта';
 
console.log( str );

Далее рассмотрим частые свойства и методы, которые имеются у строковых переменных и литералов.

length

Свойство length содержит длину строки, например:

let str = 'Hello!\nI\'m Javascript.';
 
console.log( str.length );

Увидим в консоле длину строки str. Обратите внимание, что length – это свойство, а не метод, поэтому вот такое обращение str.length() работать не будет.

[] и charAt

Из любой строки можно взять отдельный символ. Это делается с помощью оператора [], в которых указывается индекс нужного символа. Например:

let str = 'Hello!\nI\'m Javascript.';
let ch1 = str[0];
let ch2 = str[7];
console.log(ch1, ch2);
console.log(typeof ch1);

Обратите внимание, что так как в JavaScript нет символьного типа, то возвращаемое значение – это строка, состоящая из одного символа.

Ту же самую операцию выделения символа можно выполнить и с помощью метода charAt(pos), но он менее удобен и существует, скорее по историческим причинам для совместимости со старыми скриптами:

let ch1 = str.charAt(0);
let ch2 = str.charAt(7);

Интересной особенностью JavaScript является возможность перебрать строку посимвольно с помощью цикла for of, используемого для массивов:

for(let ch of "Hello")
   console.log(ch);

Обратите внимание, что строки в JavaScript изменять нельзя. Например, нельзя выполнить такую операцию:

str[0] = "h";

получим ошибку исполнения. Если нужно изменить строку, то создается новая измененная строка.

toLowerCase() и toUpperCase()

Данные методы возвращают строку в нижнем и верхнем регистрах. Например:

let str = 'Hello!';
let low = str.toLowerCase();
let hi = "string".toUpperCase();
console.log(low, hi);

Обратите внимание, что мы можем вызывать методы непосредственно у строковых литералов, а не только у переменных.

infexOf и lastIndexOf

Данный метод выполняет поиск подстроки substr, начиная с позиции pos:

str.indexOf(substr[, pos])

возвращает позицию, на которой располагается совпадение, либо -1 если совпадений не найдено.

let str = '<span class="clock">12:34</span>';
let indx1 = str.indexOf("clock");          // 13
let indx2 = str.indexOf("span", 2);        // 27
let indx3 = str.indexOf("div");            // -1
 
console.log(indx1, indx2, indx3);

Обратите внимание, данный метод находит только одно первое совпадение, дальше поиск не продолжается. Если нужно найти все совпадения, то можно реализовать такой простой алгоритм:

let indx = -1;
 
while(true) {
    indx = str.indexOf("span", indx+1);
    if(indx == -1) break;
    console.log(indx);
}

Другой похожий метод

str.lastIndexOf(substr, position)

ищет подстроку с конца строки к началу. Он используется тогда, когда нужно получить самое последнее вхождение:

let indx = str.lastIndexOf("span");
console.log(indx);

includes, startsWith, endsWith

Следующие три метода позволяют проверять: есть ли в строке искомая подстрока. Первый метод имеет ожидаемый синтаксис:

str.includes(substr[, pos])

он возвращает true, если подстрока substr была найдена в строке str и false в противном случае. Второй необязательный параметр pos указывает начальный индекс для поиска. Вот примеры использования данного метода:

let str = '<span class="clock">12:34</span>';
console.log( str.includes("span") );
console.log( str.includes("<span>") );
console.log( str.includes("clock", 20) );

Следующие два метода startsWith и endsWith проверяют, соответственно, начинается ли и заканчивается ли строка определённой строкой:

console.log( str.startsWith("span") );      //false
console.log( str.startsWith("<span") );        //true
console.log( str.endsWith("span>") );        //true

slice

Есть три основных метода для выделения подстрок из строки – это substring, substr и slice. Метод slice имеет следующий синтаксис:

str.slice(start [, end])

и возвращает часть строки от start до end (не включая его). Например:

console.log( str.slice(0, 5) );         //<span
console.log( str.slice(6, 11) );        //class
console.log( str.slice(12) );           //"clock"...
console.log( str.slice(-7, -1) );       //</span

Следующий метод

str.substring(start [, end])

работает практически также как и slice, но здесь аргумент start может быть больше, чем end, например:

console.log( str.substring(6, 11) );     //class
console.log( str.substring(11, 6) );     //class

Но отрицательные значения записывать нельзя, они будут трактоваться как 0.

Последний метод

str.substr(start [, length])

Возвращает часть строки, начиная с индекса start и длиной в length символов. В противоположность предыдущим методам, здесь указывается длина вместо конечной позиции:

console.log( str.substr(6, 13) );     //class = "clock"
console.log( str.substr(12) );        //"clock">12:34</span>

При отрицательном значении первого аргумента позиция отсчитывается с конца строки.

Какой из этих трех методов выбирать для выделения строк? По большому счету без разницы. Они все работают эффективно, так что это дело предпочтения программиста.

Нюансы сравнения строк

Если мы проверяем строки на равенство, то никаких особых проблем в JavaScript это не вызывает, например:

if("abc" == "abc") console.log( "строки равны" );
if("abc" != "ABC") console.log( "строки не равны" );

Но, когда мы используем знаки больше/меньше, то строки сравниваются в лексикографическом порядке. То есть:

1. Если код текущего символа одной строки больше кода текущего символа другой строки, то первая строка больше второй (остальные символы не имеют значения), например:

console.log( "z" > "Za" );        //true

2. Если код текущего символа одной строки меньше кода текущего символа другой строки, то первая строка меньше второй:

console.log( "B" < "a" );    //true

3. При равенстве символов больше та строка, которая содержит больше символов:

console.log( "abc" < "abcd" ); //true

4. В остальных случаях строки равны:

console.log( "abc" == "abc" ); //true

Но в этом алгоритме есть один нюанс. Например, вот такое сравнение:

console.log( "Америка" > "Japan" );    //true

Дает значение true, так как русская буква A имеет больший код, чем латинская буква J. В этом легко убедиться, воспользовавшись методом

str.codePointAt(pos)

который возвращает код символа, стоящего в позиции pos:

console.log( "А".codePointAt(0), "J".codePointAt(0) );

Сморите, у буквы А код равен 1040, а у буквы J – 74. Напомню, что строки в JavaScript хранятся в кодировке UTF-16. К чему может привести такой результат сравнения? Например, при сортировке мы получим на первом месте страну «Japan», а потом «Америка». Возможно, это не то, что нам бы хотелось? И здесь на помощь приходит специальный метод для корректного сравнения таких строк:

str.localeCompare(compareStr)

он возвращает отрицательное число, если str < compareStr, положительное при str > compareStr и 0 если строки равны. Например:

console.log( "Америка".localeCompare("Japan") );      // -1

возвращает -1 как и должно быть с учетом языкового сравнения. У этого метода есть два дополнительных аргумента, которые указаны в документации JavaScript. Первый позволяет указать язык (по умолчанию берётся из окружения) — от него зависит порядок букв. Второй позволяет определять дополнительные правила, например, чувствительность к регистру.

Некоторые другие методы

У строковых переменных есть еще пара полезных и часто используемых методов, это:

str.trim()

убирает пробелы в начале и конце строки:

let str = "   string   ";
console.log( str.trim() );

И

str.repeat(n)

для повторения строки n раз:

let str = "Abc";
console.log( str.repeat(5) );

Это, конечно, не все методы строк. По мере использования JavaScript вы познакомитесь со многими другими, но для начала этого будет достаточно. Также отдельно стоит тема регулярных выражений – мощнейший инструмент для поиска, замены и проверки различных строковых шаблонов, но об этом мы будем говорить на отдельном занятии.

Видео по теме