Лекция
Привет, сегодня поговорим про строки в javascript, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое строки в javascript , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
length
substr
, substring
, slice
.В JavaScript любые текстовые данные являются строками. Не существует отдельного типа «символ», который есть в ряде других языков.
Внутренним форматом строк, вне зависимости от кодировки страницы, является Юникод (Unicode).
Строки создаются при помощи двойных или одинарных кавычек:
1 |
var text = "моя строка" ; |
2 |
3 |
var anotherText = 'еще строка' ; |
4 |
5 |
var str = "012345" ; |
В JavaScript нет разницы между двойными и одинарными кавычками.
Строки могут содержать специальные символы. Самый часто используемый из таких символов — этоперевод строки.
Он обозначается как \n
, например:
1 |
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' ; |
В двойных кавычках — экранируются внутренние двойные:
1 |
var str = "I'm a JavaScript \"programmer\" " ; |
2 |
alert(str); |
Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без '\'
. Вы можете увидеть это, запустив пример выше.
Сам символ обратного слэша '\'
является служебным, поэтому всегда экранируется, т.е пишется как\\
:
1 |
var str = ' символ \\ ' ; |
2 |
3 |
alert(str); // символ \ |
Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдет:
1 |
alert( "\a" ); // a |
2 |
// идентично alert( "a" ); |
Здесь мы рассмотрим методы и свойства строк, с некоторыми из которых мы знакомились ранее, в главе Методы и свойства.
length
Одно из самых частых действий со строкой — это получение ее длины:
1 |
var str = "My\n" ; // 3 символа. Третий - перевод строки |
2 |
3 |
alert(str.length); // 3 |
Чтобы получить символ, используйте вызов charAt(позиция)
. Первый символ имеет позицию 0
:
1 |
var str = "jQuery" ; |
2 |
alert( str.charAt(0) ); // "j" |
В JavaScript нет отдельного типа «символ», так что charAt
возвращает строку, состоящую из выбранного символа.
В современных браузерах (не IE7-) для доступа к символу можно также использовать квадратные скобки:
1 |
var str = "Я - современный браузер!" ; |
2 |
alert(str[0]); // "Я", IE8+ |
Разница между этим способом и charAt
заключается в том, что если символа нет —charAt
выдает пустую строку, а скобки — undefined
:
1 |
alert( "" .charAt(0) ); // пустая строка |
2 |
alert( "" [0] ); // undefined, IE8+ |
Обратите внимание, str.length
— это свойство строки, а str.charAt(pos)
—метод, т.е. функция.
Обращение к методу всегда идет со скобками, а к свойству — без скобок.
строки в javascript нельзя изменять. Можно прочитать символ, но нельзя заменить его. Как только строка создана — она такая навсегда.
Чтобы это обойти, создается новая строка и присваивается в переменную вместо старой:
1 |
var str = "строка" ; |
2 |
3 |
str = str.charAt(3) + str.charAt(4) + str.charAt(5); |
4 |
5 |
alert(str); // ока |
Методы toLowerCase()
и toUpperCase()
меняют регистр строки на нижний/верхний:
1 |
alert( "Интерфейс" .toUpperCase() ); // ИНТЕРФЕЙС |
Пример ниже получает первый символ и приводит его к нижнему регистру:
alert( "Интерфейс" .charAt(0).toLowerCase() ); // 'и' |
Для поиска подстроки есть метод indexOf(подстрока[, начальная_позиция]).
Он возвращает позицию, на которой находится подстрока
или -1
, если ничего не найдено. Например:
1 |
var str = "Widget with id" ; |
2 |
3 |
alert( str.indexOf( "Widget" ) ); // 0, т.к. "Widget" найден прямо в начале str |
4 |
alert( str.indexOf( "id" ) ); // 1, т.к. "id" найден, начиная с позиции 1 |
5 |
alert( str.indexOf( "Lalala" ) ); // -1, подстрока не найдена |
Необязательный второй аргумент позволяет искать, начиная с указанной позиции. Об этом говорит сайт https://intellect.icu . Например, первый раз "id"
появляется на позиции 1
. Чтобы найти его следующее появление — запустим поиск с позиции2
:
1 |
var str = "Widget with id" ; |
2 |
3 |
alert( str.indexOf( "id" , 2) ) // 12, поиск начат с позиции 2 |
Также существует аналогичный метод lastIndexOf, который ищет не с начала, а с конца строки.
Для красивого вызова indexOf
применяется побитовый оператор НЕ '~'
.
Дело в том, что вызов ~n
эквивалентен выражению -(n+1)
, например:
1 |
alert( ~2 ); // -(2+1) = -3 |
2 |
alert( ~1 ); // -(1+1) = -2 |
3 |
alert( ~0 ); // -(0+1) = -1 |
4 |
alert( ~-1 ); // -(-1+1) = 0 |
Как видно, ~n
— ноль только в случае, когда n == -1
.
То есть, проверка if ( ~str.indexOf(...) )
означает, что результат indexOf
отличен от `-1, т.е. совпадение есть.
Вот так:
1 |
var str = "Widget" ; |
2 |
3 |
if ( ~str.indexOf( "get" ) ) { |
4 |
alert( 'совпадение есть!' ); |
5 |
} |
Вообще, использовать возможности языка неочевидным образом не рекомендуется, поскольку ухудшает читаемость кода.
Однако, в данном случае, все в порядке. Просто запомните: '~'
читается как «не минус один», а "if ~str.indexOf"
читается как "если найдено"
.
Чтобы найти все вхождения подстроки, нужно запустить indexOf
в цикле. Как только получаем очередную позицию — начинаем следующий поиск со следующей.
Пример такого цикла:
01 |
var str = "Ослик Иа-Иа посмотрел на виадук" ; // ищем в этой строке |
02 |
var target = "Иа" ; // цель поиска |
03 |
04 |
var pos = 0; |
05 |
while ( true ) { |
06 |
var foundPos = str.indexOf(target, pos); |
07 |
if (foundPos == -1) break ; |
08 |
09 |
alert(foundPos); // нашли на этой позиции |
10 |
pos = foundPos + 1; // продолжить поиск со следующей |
11 |
} |
Такой цикл начинает поиск с позиции 0
, затем найдя подстроку на позиции foundPos
, следующий поиск продолжит с позиции pos = foundPos+1
, и так далее, пока что-то находит.
Впрочем, тот же алгоритм можно записать и короче:
1 |
var str = "Ослик Иа-Иа посмотрел на виадук" ; // ищем в этой строке |
2 |
var target = "Иа" ; // цель поиска |
3 |
4 |
var pos = -1; |
5 |
while ( (pos = str.indexOf(target, pos+1)) != -1) { |
6 |
alert(pos); |
7 |
} |
substr
, substring
, slice
.В JavaScript существуют целых 3 (!) метода для взятия подстроки, с небольшими отличиями между ними.
substring(start [, end])
substring(start, end)
возвращает подстроку с позиции start
до, но не включая end
.
1 |
var str = "stringify" ; |
2 |
alert(str.substring(0,1)); // "s", символы с позиции 0 по 1 не включая 1. |
Если аргумент end
отсутствует, то идет до конца строки:
1 |
var str = "stringify" ; |
2 |
alert(str.substring(2)); // ringify, символы с позиции 2 до конца |
substr(start [, length])
substring
, а второй содержит не конечную позицию, а количество символов.
1 |
var str = "stringify" ; |
2 |
str = str.substr(2,4); // ring, со 2й позиции 4 символа |
3 |
alert(str) |
Если второго аргумента нет — подразумевается «до конца строки».
slice(start [, end])
start
до, но не включая, позиции end
. Смысл параметров — такой же как в substring
.Различие между substring
и slice
— в том, как они работают с отрицательными и выходящими за границу строки аргументами:
substring(start, end)
1 |
alert( "testme" .substring(-2) ); // "testme", -2 становится 0 |
Кроме того, если start > end
, то аргументы меняются местами, т.е. возвращается участок строки между start
и end
:
1 |
alert( "testme" .substring(4, -1) ); // "test" |
2 |
// -1 становится 0 -> получили substring(4, 0) |
3 |
// 4 > 0, так что аргументы меняются местами -> substring(0, 4) = "test" |
slice
1 |
alert( "testme" .slice(-2) ); // "me", от 2 позиции с конца |
1 |
alert( "testme" .slice(1, -1) ); // "estm", от 1 позиции до первой с конца. |
Это гораздо более удобно, чем странная логика substring
.
Отрицательное значение первого параметра поддерживается в substr
во всех браузерах, кроме IE8-.
Выводы.
Самый удобный метод — это slice(start, end)
.
В качестве альтернативы можно использовать substr(start, length)
, помня о том, что IE8- не поддерживает отрицательный start
.
Если вы знакомы со сравнением строк в других языках, то позвольте предложить одну маленькую загадку. Даже не одну, а целых две.
Как мы знаем, символы сравниваются в алфавитном порядке 'А' < 'Б' < 'В' < ... < 'Я'
.
Но есть несколько странностей..
'а'
маленькая больше буквы 'Я'
большой?
1 |
alert( 'а' > 'Я' ); // true |
'е'
находится в алфавите между е
и ж
: абвгдеежз..
. Но почему тогда 'е'
больше 'я'
?
1 |
alert( 'е' > 'я' ); // true |
Чтобы разобраться с этим, обратимся к внутреннему представлению строк в JavaScript.
Все строки имеют внутреннюю кодировку Юникод.
Неважно, на каком языке написана страница, находится ли она в windows-1251 или utf-8. Внутри JavaScript-интерпретатора все строки приводятся к единому «юникодному» виду. Каждому символу соответствует свой код.
Есть метод для получения символа по его коду:
code
:
1 |
alert( String.fromCharCode(1072) ); // 'а' |
… И метод для получения цифрового кода из символа:
pos
. Отсчет позиции начинается с нуля.
1 |
alert( "абрикос" .charCodeAt(0) ); // 1072, код 'а' |
Теперь вернемся к примерам выше. Почему сравнения 'е' > 'я'
и 'а' > 'Я'
дают такой странный результат?
Дело в том, что символы сравниваются не по алфавиту, а по коду. У кого код больше — тот и больше. В юникоде есть много разных символов. Кириллическим буквам соответствует только небольшая часть из них, подробнее — Кириллица в Юникоде.
Выведем отрезок символов юникода с кодами от 1034
до 1113
:
1 |
var str = '' ; |
2 |
for ( var i=1034; i<=1113; i++) { |
3 |
str += String.fromCharCode(i); |
4 |
} |
5 |
alert(str); |
ЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐеђѓєѕіїјљ
Мы можем увидеть из этого отрезка две важных вещи:
'а'(код 1072) > 'Я'(код 1071)
.'a' > 'Z'
.е
, находятся вне основного алфавита.е
имеет код, больший чем я
, поэтому'е'(код 1105) > 'я'(код 1103)
.Ё
располагается в Unicode до А
, поэтому 'Ё'
(код 1025) < 'А'
(код 1040). Удивительно: есть буква меньше чем А
Кстати, если мы знаем код символа в кодировке юникод, то можем добавить его в HTML, используя «числовую ссылку» (numeric character reference).
Для этого нужно написать сначала &#
, затем код, и завершить точкой с запятой ';'
. Например, символ 'а'
в виде числовой ссылки: а
.
Если код хотят дать в 16-ричной системе счисления, то начинают с &#x
.
В юникоде есть много забавных и полезных символов, например, символ ножниц: ✂ (✂
), дроби: ½ (½
) ¾ (¾
) и другие. Их можно удобно использовать вместо картинок в дизайне.
Строки сравниваются лексикографически, в порядке «телефонного справочника».
Сравнение строк s1
и s2
обрабатывается по следующему алгоритму:
a = s1.charAt(0)
и b = s2.charAt(0)
. Если они одинаковы, то следующий шаг, иначе, в зависимости от результата их сравнения, возвратить true
или false
Спецификация языка определяет этот алгоритм более детально, но смысл в точности соответствует порядку, по которому имена заносятся в телефонный справочник.
"Z" > "A" // true |
"Вася" > "Ваня" // true, т.к. с > н |
"aa" > "a" // true, т.к. начало совпадает, но в 1й строке больше символов |
Бывает, что числа приходят в скрипт в виде строк, например как результат prompt
. В этом случае результат их сравнения будет неверным:
1 |
alert( "2" > "14" ); // true, так как это строки, и для первых символов верно "2" > "1" |
Если хотя бы один аргумент — не строка, то другой будет преобразован к числу:
1 |
alert(2 > "14" ); // false |
\n
и вставлять юникодные символы по коду.length
и методами charAt
, toLowerCase/toUpperCase
,substring/substr/slice
(предпочтителен slice
)е
вообще вне основного алфавита.a = 'my string' |
b = new String(object) // синтаксис устарел и не используется |
c = String(object) |
string - Необязательный. Любая группа знаков Юникода.
Объекты String
, как правило, создаются неявно с помощью строковых литералов.
// кавычки любые - без разницы |
var str = "string literal" |
В строковых литералах можно использовать escape-последовательности для представления особых знаков, которые нельзя напрямую использовать в строках, например символа перевода строки или знаков Юникода. При компиляции сценария каждая escape-последовательность в строковом литерале преобразуется в знаки, которые она представляет.
Можно указать юникодный символ явным образом, через его код.
var str = "\u1234" |
Объекты String
, заданные через кавычки (и называемые "примитивными" строками), немного отличаются от объектов String
, созданных с помощью оператора new. Так, например, типом (typeof) данных объекта, созданного при помощи new
, является'object'
, а не 'string'
. И такому объекту можно напрямую назначать дополнительные свойства и методы. В остальном - интерпретатор автоматически превращает примитивные строки в объекты.
"12345" .length // 5 |
Доступ к символам осуществляется при помощи метода String#charAt
return 'cat' .charAt(1); // возвратит "a" |
Также существует отсутствующий в стандарте ECMA-262 способ - обращение к строке как к массиву:
var str = 'cat' |
return str[1] // "a" |
В отличие от языков C/PHP/и т.п., однажды созданную строку нельзя изменить: символы можно только считывать, но не менять.
Для изменения строковой переменной применяется присваивание измененной строки:
str = "строка" |
str = str.charAt(4) + str.charAt(5) + str.charAt(6) // "ока" |
Для сравнения строк используются обычные операторы < >.
К сожалению, в одной статье не просто дать все знания про строки в javascript. Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое строки в javascript и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)