Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

Строки

  1. Создание строк
    1. Специальные символы
    2. Экранирование специальных символов
  2. Методы и свойства
    1. Длина length
    2. Доступ к символам
    3. Изменения строк
    4. Смена регистра
    5. Поиск подстроки
    6. Взятие подстроки: substr, substring, slice.
  3. Кодировка Юникод
  4. Сравнение строк
  5. Итого

В JavaScript любые текстовые данные являются строками. Даже один символ - строка.

Все строки, вне зависимости от кодировки, хранятся в формате Юникод (Unicode).

Создание строк

Строки создаются при помощи двойных или одинарных кавычек:

var text = "моя строка";

var anotherText = 'еще строка';

var str = "012345";

В JavaScript нет разницы между двойными и одинарными кавычками.

Специальные символы

Строки могут содержать специальные символы. Самый часто используемый из таких символов - это перевод строки.

Он обозначается как \n, например:

alert('Привет\nМир'); // выведет "Мир" на новой строке

Есть и более редкие символы, вот их список:

Специальные символы
Символ Описание
\b Backspace
\f Form feed
\n New line
\r Carriage return
\t Tab
\uNNNN Символ в кодировке Юникод с шестнадцатиричным кодом NNNN. Например, \u00A9 - юникодное представление символа копирайт ©

Экранирование специальных символов

Если строка в одинарных кавычках, то внутренние одинарные кавычки внутри должны быть экранированы, то есть снабжены обратным слешем \', вот так:

var str = '*!*I\'m*/!* a JavaScript programmer';

В двойных кавычках — экранируются внутренние двойные:

var str = "I'm a JavaScript \"programmer\" ";
alert(str);

Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без '\'. Вы можете увидеть это, запустив пример выше.

Сам символ обратного слэша '\' является служебным, поэтому всегда экранируется, т.е пишется как \\:

var str = ' символ \\ ';

alert(str); // символ \

Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдёт:

alert( "\a" ); // a
// идентично alert( "a" );

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

Здесь мы рассмотрим методы и свойства строк, с некоторыми из которых мы знакомились ранее, в главе Методы и свойства.

Длина length

Одно из самых частых действий со строкой — это получение ее длины:

var str = "My\n"; // 3 символа. Третий - перевод строки

alert(str.length);  // 3

Доступ к символам

Чтобы получить символ, используйте вызов charAt(позиция). Первый символ имеет позицию 0:

var str = "jQuery";
alert( str.charAt(0) );  // "j"

В JavaScript нет отдельного типа «символ», так что charAt возвращает строку, состоящую из выбранного символа.

В современных браузерах (кроме IE<8) для доступа к символу можно также использовать квадратные скобки:

var str = "Я - современный браузер!";
alert(str[0]);  // "Я", IE8+

Разница между этим способом и charAt заключается в том, что если символа нет — charAt выдает пустую строку, а скобки — undefined:

alert( "".charAt(0) ); // пустая строка
alert( ""[0] ); // undefined, IE8+

Вызов метода — всегда со скобками

Обратите внимание, str.length — это свойство строки, а str.charAt(pos)метод, т.е. функция.

Обращение к методу всегда идет со скобками, а к свойству — без скобок.

Изменения строк

Строки в JavaScript нельзя изменять. Можно прочитать символ, но нельзя заменить его. Как только строка создана — она такая навсегда.

Чтобы это обойти, создаётся новая строка и присваивается в переменную вместо старой:

var str = "строка";

str =  str.charAt(3) + str.charAt(4) + str.charAt(5);

alert(str); // ока

Смена регистра

Методы toLowerCase() и toUpperCase() меняют регистр строки на нижний/верхний:

alert( "Интерфейс".toUpperCase() ); // ИНТЕРФЕЙС

Пример ниже получает первый символ и приводит его к нижнему регистру:

alert( "Интерфейс".charAt(0).toLowerCase() ); // 'и'

Напишите функцию ucFirst(str), которая возвращает строку str с заглавным первым символом, например:

ucFirst("вася") == "Вася"

P.S. В JavaScript нет встроенного метода для этого. Создайте функцию, используя toUpperCase() и charAt().

Решение
Решение

Мы не можем просто заменить первый символ, т.к. строки в JavaScript неизменяемы.

Единственный способ - пересоздать строку на основе существующей, но с заглавным первым символом:

function ucFirst(str) {
  var newStr = str.charAt(0).toUpperCase();

  for(var i=1; i<str.length; i++) {
    newStr += str.charAt(i);
  }

  return newStr;
}

alert( ucFirst("вася") );

P.S. Существуют и другие решения, использующие метод substr, а также регулярные выражения.

Поиск подстроки

Для поиска подстроки есть метод indexOf(подстрока[, начальная_позиция]).

Он возвращает позицию, на которой находится подстрока или -1, если ничего не найдено. Например:

var str = "Widget with id";

alert( str.indexOf("Widget") ); // 0, т.к. "Widget" найден прямо в начале str
alert( str.indexOf("id") ); // 1, т.к. "id" найден, начиная с позиции 1
alert( str.indexOf("Lalala") ); // -1, подстрока не найдена

Необязательный второй аргумент позволяет искать, начиная с указанной позиции. Например, первый раз "id" появляется на позиции 1. Чтобы найти его следующее появление - запустим поиск с позиции 2:

var str = "Widget with id";

alert( str.indexOf("id", 2) ) // 12, поиск начат с позиции 2

Также существует аналогичный метод lastIndexOf, который ищет не с начала, а с конца строки.

Для красивого вызова indexOf применяется побитовый оператор НЕ '~'.

Дело в том, что вызов ~n эквивалентен выражению -(n+1), например:

alert( ~2 ); // -(2+1) = -3
alert( ~1 ); // -(1+1) = -2
alert( ~0 ); // -(0+1) = -1
*!*
alert( ~-1 ); // -(-1+1) = 0
*/!*

Как видно, ~n - ноль только в случае, когда n == -1.

То есть, проверка if ( ~str.indexOf(...) ) означает, что результат indexOf отличен от `-1, т.е. совпадение есть.

Вот так:

var str = "Widget";

if( ~str.indexOf("get") ) {
  alert('совпадение есть!');
}

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

Однако, в данном случае, все в порядке. Просто запомните: '~' читается как «не минус один», а "if ~str.indexOf" читается как "если найдено".

Напишите функцию checkSpam(str), которая возвращает true, если строка str содержит ‘viagra’ or ‘XXX’.

Функция должна быть нечувствительна к регистру:

checkSpam('buy ViAgRA now') == true
checkSpam('free xxxxx') == true
checkSpam("innocent rabbit") == false

Решение
Решение

Метод indexOf ищет совпадение с учетом регистра. То есть, в строке 'xXx' он не найдет 'XXX'.

Для проверки приведем к нижнему регистру и строку str и то, что будем искать:

function checkSpam(str) {
  str = str.toLowerCase();
       
  return str.indexOf('viagra') >= 0 || str.indexOf('xxx') >= 0;
}

Полное решение: tutorial/intro/checkSpam.html.

Взятие подстроки: substr, substring, slice.

В JavaScript существуют целых 3 (!) метода для взятия подстроки, с небольшими отличиями между ними.

substring(start [, end])
Метод substring(start, end) возвращает подстроку с позиции start до, но не включая end.

var str = "*!*s*/!*tringify";
alert(str.substring(0,1)); // "s", символы с позиции 0 по 1 не включая 1.

Если аргумент end отсутствует, то идет до конца строки:

var str = "st*!*ringify*/!*";
alert(str.substring(2)); // ringify, символы с позиции 2 до конца

substr(start [, length])
Первый аргумент имеет такой же смысл, как и в substring, а второй содержит не конечную позицию, а количество символов.

var str = "st*!*ring*/!*ify";
str = str.substr(2,4); // ring, со 2й позиции 4 символа 
alert(str)

Если второго аргумента нет - подразумевается «до конца строки».

slice(start [, end])
Возвращает часть строки от позиции start до, но не включая, позиции end. Смысл параметров - такой же как в substring.

Различие между substring и slice - в том, как они работают с отрицательными и выходящими за границу строки параметрами:

substring(start, end)
Отрицательные аргументы интерпретируются как равные нулю. Слишком большие значения усекаются до длины строки:

alert( "testme".substring(-2) );  // "testme", -2 становится 0

Кроме того, если start > end, то аргументы меняются местами, т.е. возвращается участок строки между start и end:

alert( "testme".substring(4, -1) );  // "test"
// -1 становится 0 -> получили substring(4, 0) 
// 4 > 0, так что аргументы меняются местами -> substring(0, 4) = "test"

slice
Отрицательные значения отсчитываются от конца строки:

alert( "testme".slice(-2) );  // "me", от 2 позиции с конца

alert( "testme".slice(1, -1) ); // "estm", от 1 позиции до первой с конца.

Это гораздо более удобно, чем странная логика substring.

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

Выводы.

Самый удобный метод - это slice(start, end).

В качестве альтернативы можно использовать substr(start, length). При этом start должен быть неотрицательным для IE.

Создайте функцию truncate(str, maxlength), которая проверяет длину строки str, и если она превосходит maxlength — заменяет конец str на '…', так чтобы ее длина стала равна maxlength.

Результатом функции должна быть (при необходимости) усечённая строка.

Например:

truncate("Вот, что мне хотелось бы сказать на эту тему:", 20)) = "Вот, что мне хотело…"

truncate("Всем привет!", 20)) = "Всем привет!"

Эта функция имеет применение в жизни. Она используется, чтобы усекать слишком длинные темы сообщений.

Решение
Решение

Так как окончательная длина строки должна быть maxlength, то нужно её обрезать немного короче, чтобы дать место для троеточия.

function truncate(str, maxlength) {
  if (str.length > maxlength) {
    return str.slice(0, maxlength - 3) + '...';
    // итоговая длина равна maxlength
  }

  return str;
}

alert(truncate("Вот, что мне хотелось бы сказать на эту тему:", 20))
alert(truncate("Всем привет!", 20))

Ещё лучшим вариантом будет использование вместо трёх точек специального символа «троеточие»: (…), тогда можно отрезать один символ.

function truncate(str, maxlength) {
  if (str.length > maxlength) {
    return str.slice(0, maxlength - 1) + '…';
  }

  return str;
}

alert(truncate("Вот, что мне хотелось бы сказать на эту тему:", 20))
alert(truncate("Всем привет!", 20))

Можно было бы написать этот код короче:

function truncate(str, maxlength) {
  return (str.length > maxlength) ? 
    str.slice(0, maxlength - 1) + '…' : str;
}

alert(truncate("Вот, что мне хотелось бы сказать на эту тему:", 20))
alert(truncate("Всем привет!", 20))

Кодировка Юникод

Если вы знакомы со сравнением строк в других языках, то позвольте предложить одну маленькую загадку. Даже не одну, а целых две.

Как мы знаем, символы сравниваются в алфавитном порядке 'А' < 'Б' < 'В' < ... < 'Я'.

Но есть несколько странностей..

  1. Почему буква 'а' маленькая больше буквы 'Я' большой?
    alert( 'а' > 'Я' ); // true
    
  2. Буква 'ё' находится в алфавите между е и ж: абвгдеёжз... Но почему тогда 'ё' больше 'я'?
    alert( 'ё' > 'я' ); // true
    

Чтобы разобраться с этим, обратимся к внутреннему представлению строк в JavaScript.

Все строки имеют внутреннюю кодировку Юникод.

Вообще, в мире много разных кодировок, и страница может быть в любой из них. Но внутри JavaScript-интерпретатора все строки находятся в кодировке юникод.

Есть метод для получения символа по его цифровому коду:

String.fromCharCode(code)
Возвращает символ по коду code:
alert( String.fromCharCode(1072) ); // 'а'

… И метод для получения цифрового кода:

str.charCodeAt(pos)
Возвращает код символа на позиции pos. Отсчет позиции начинается с нуля.
alert( "абрикос".charCodeAt(0) ); // 1072, код 'а'

Теперь вернемся к примерам выше. Почему сравнения 'ё' > 'я' и 'а' > 'Я' дают такой странный результат?

Дело в том, что символы сравниваются не по алфавиту, а по коду. У кого код больше — тот и больше. В юникоде есть много разных символов. Славянским языкам соответствуют коды примерно от 1024 до 1119.

Так их можно получить:

var s = '';
for (var i=1024; i<=1119; i++) {
  s += String.fromCharCode(i);
}
Результат:

?ЁЂЃЄЅІЇЈЉЊЋЌ?ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя?ёђѓєѕіїјљњћќ?ўџ

Промежуток взят «с запасом», так что можно увидеть некириллические символы в начале и в конце.

Мы можем увидеть из этого отрезка кодировки две вещи:

  1. Строчные буквы идут после заглавных, поэтому они всегда больше.
    В частности, 'а'(код 1072) > 'Я'(код 1071).
    Кстати, то же самое и в английском алфавите, там 'a' > 'Z'.
  2. Ряд букв, например ё, находятся вне основного алфавита.
    Это объясняет, почему 'ё'(код 1105) > 'я'(код 1103).

Юникод в HTML

Кстати, если мы знаем код символа в кодировке юникод, то можем использовать его и в HTML.

Чтобы вставить символ с данным кодом в HTML, нужно написать сначала &#, затем код, и завершить точкой с запятой ';'. Например, буква 'а'в HTML: &#1072;.

Если код хотят дать в 16-ричной системе счисления, то начинают с &#x.

Например, символ ножниц: ✂(&#x2702;), дроби: ½ (&#xBD;) ¾ (&#xBE;). В юникоде есть и много других забавных символов.

Сравнение строк

Строки сравниваются лексикографически, в порядке «телефонного справочника».

Сравнение строк s1 и s2 обрабатывается по следующему алгоритму:

  1. Сравниваются первые символы: a = s1.charAt(0) и b = s2.charAt(0). Если они одинаковы, то следующий шаг, иначе, в зависимости от результата их сравнения, возвратить true или false
  2. Сравниваются вторые символы, затем третьи и так далее… Если в одной строке закончились символы, то она меньше. Если в обоих закончились - они равны.

Спецификация языка определяет этот алгоритм более детально, но смысл в точности соответствует порядку, по которому имена заносятся в телефонный справочник.

"Z" > "A" // true
"Вася" > "Ваня" // true, т.к. с > н
"aa" > "a"  // true, т.к. начало совпадает, но в 1й строке больше символов

Числа в виде строк

Обратим внимание на результат сравнения чисел в строковой форме. Он может быть неверным:

alert("2" > "14"); // true, т.к. это строки и "2" > "1"

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

alert(2 > "14"); // false

Итого

  • Строки в JavaScript имеют внутреннюю кодировку Юникод. При написании строки можно использовать спец. символы и вставлять юникодные символы по коду.
  • Мы познакомились со свойством length и методами charAt, toLowerCase/toUpperCase, substring/substr/slice (предпочтителен slice)
  • Строки сравниваются побуквенно. Поэтому если число получено в виде строки, то такие числа могут сравниваться некорректно, нужно преобразовать его к типу number.

Больше информации о методах для строк можно получить в справочнике: http://javascript.ru/String.


Комментарии

  1. Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  2. Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
  3. Комментарии без смысла, с рекламой или не о статье вообще - удаляются.
Наверх

Содержание

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!