String.prototype.replace()
Содержание:
- Большинство методов поддерживают «thisArg»
- Спецсимволы
- Строковые примитивы и объекты String
- Обратные символьные классы
- Циклы for
- Поиск в массиве
- Строковые методы, поиск и замена
- Итерируемые объекты и псевдомассивы
- Статичные регэкспы
- includes, startsWith, endsWith
- indexOf
- substr
- Две стадии преобразования
- Свойство Access
- Некоторые другие методы
- Свойства строк
Большинство методов поддерживают «thisArg»
Почти все методы массива, которые вызывают функции – такие как , , , за исключением метода , принимают необязательный параметр .
Этот параметр не объяснялся выше, так как очень редко используется, но для наиболее полного понимания темы мы обязаны его рассмотреть.
Вот полный синтаксис этих методов:
Значение параметра становится для .
Например, вот тут мы используем метод объекта как фильтр, и передаёт ему контекст:
Если бы мы в примере выше использовали просто , то вызов был бы в режиме отдельной функции, с . Это тут же привело бы к ошибке.
Вызов можно заменить на , который делает то же самое. Последняя запись используется даже чаще, так как функция-стрелка более наглядна.
Спецсимволы
Если мы применяем одинарные либо двойные кавычки, мы тоже можем создавать многострочные строки. Для этого понадобится символ перевода строки \n:
let guestList = "Guests:\n * Bob\n * Petr\n * Maria"; alert(guestList); // список гостей из нескольких строк
Две строки ниже являются эквивалентными. Разница в том, что они по-разному записаны:
// используем спецсимвол перевода строки let str1 = "Hello\nWorld"; // используем обратные кавычки let str2 = `Hello World`; alert(str1 == str2); // true
Существует и масса других спецсимволов:
Рассмотрим парочку примеров с Юникодом:
// alert( "\u00A9" ); // Длинные коды // 佫, редкий китайский иероглиф alert( "\u{20331}" ); // , улыбающийся смайлик с глазами-сердечками alert( "\u{1F60D}" );
Как правило, спецсимволы начинаются с символа экранирования, представляющего собой обратный слеш \. Его можно использовать и для того, чтобы вставлять в строки кавычки:
alert( 'I\'m the God!' ); // I'm the God!
Но экранировать нужно только тогда, когда внутри строки мы используем такие же кавычки, в которые эта самая строка заключена. Таким образом, можно поступать проще:
alert( `I'm the Walrus!` ); // I'm the Walrus!
Как видите, мы поместили строку в косые кавычки, а раздели I’m одинарной кавычкой. Просто и элегантно.
Кстати, если вдруг потребуется добавить в нашу строку сам обратный слеш, то мы экранируем его вторым обратным слешем:
alert( `The backslash: \\` ); // The backslash: \
Строковые примитивы и объекты String
В JavaScript существует два типа строк. JavaScript различает строковый примитив (неизменный тип данных) и объект String.
Чтобы понять разницу между ними, инициализируйте строковый примитив и объект String.
Оператор typeof позволяет определить тип значения. В первом случае строка была просто присвоена переменной.
Во втором случае с помощью new String() был создан объект и присвоен переменной.
В основном используются примитивы строк. JavaScript может использовать встроенные свойства и методы оболочки объекта String, не изменяя строковый примитив в объекте.
Вы должны знать различие между примитивами и объектами, хотя сначала понять ее сложно. По сути, существуют методы и свойства, доступные для всех строк, и в фоновом режиме JavaScript будет выполнять преобразование в объект и обратно в примитив каждый раз, когда вызывается метод или свойство.
Обратные символьные классы
Для каждого символьного класса существует «обратный класс», обозначаемый той же буквой, но в верхнем регистре.
«Обратный» означает, что он соответствует всем другим символам, например:
- Не цифра: любой символ, кроме , например буква.
- Не пробел: любой символ, кроме , например буква.
- Любой символ, кроме , то есть не буквы из латиницы, не знак подчёркивания и не цифра. В частности, русские буквы принадлежат этому классу.
Мы уже видели, как сделать чисто цифровой номер из строки вида : найти все цифры и соединить их.
Альтернативный, более короткий путь – найти нецифровые символы и удалить их из строки:
Циклы for
Цикл for может использовать до трех опциональных выражений для повторного выполнения блока кода.
Рассмотрим синтаксис цикла.
- Инициализация (если указано) запускает счетчик и объявляет переменные.
- Далее обрабатывается условие. Если оно истинно, программа выполнит последующий код; если оно ложно, цикл прервется.
- Затем обрабатывается код, который нужно выполнить.
- Если указано финальное выражение, оно обновляется, после чего цикл возвращается к обработке условия.
Чтобы понять, как это работает, рассмотрим базовый пример.
Если запустить этот код, вы получите такой результат:
В приведенном выше примере цикл for начинается с переменной let i = 0, которая запустит цикл со значения 0. В цикле задано условие i < 4, а это означает, что до тех пор, пока значение i меньше 4, цикл будет продолжать работу. Финальное выражение i++ определяет счетчик для каждой итерации цикла. console.log(i) выводит числа, начиная с 0, и останавливается, как только i равняется 4.
Без цикла код, выполняющий те же действия, был бы таким:
Без цикла блок кода состоит из большего количества строк. Чтобы увеличить количество чисел, пришлось бы внести в код еще больше строк.
Давайте рассмотрим каждое выражение в цикле.
Инициализация
Первое выражение в цикле – инициализация.
Оно объявляет переменную i с помощью ключевого слова let (также можно использовать ключевое слово var) и присваивет ей значение 0. Вы можете использовать в циклах любые имена переменных, но переменная i ассоциируется со словом «итерация» (iteration) и не перегружает код.
Условие
Как и циклы while и do…while, циклы for обычно имеют условие. В данном примере это:
Это значит, что выражение оценивается как истинное, пока значение i меньше 4.
Финальное выражение
Это выражение, которое выполняется в конце каждого цикла. Чаще всего оно используется для увеличения или уменьшения значения переменной, но его можно использовать и для других целей.
В данном примере цикл увеличивает переменную на единицу. Выражение i++ делает то же самое, что и i = i + 1.
В отличие от начала и условия, финальное выражение не заканчивается точкой с запятой.
Тело цикла
Теперь вы знаете все компоненты цикла for. Взглянем на код еще раз.
Первое выражение задает исходное значение переменной (0), второе определяет условие (цикл выполняется, пока i меньше 4), а третье – задает шаг каждой итерации (в данном случае значение будет увеличиваться на 1).
Консоль будет выводить значения: 0, 1, 2 и 3. Затем цикл прервется.
Поиск в массиве
Далее рассмотрим методы, которые помогут найти что-нибудь в массиве.
Методы arr.indexOf, arr.lastIndexOf и arr.includes имеют одинаковый синтаксис и делают по сути то же самое, что и их строковые аналоги, но работают с элементами вместо символов:
- ищет , начиная с индекса , и возвращает индекс, на котором был найден искомый элемент, в противном случае .
- – то же самое, но ищет справа налево.
- – ищет , начиная с индекса , и возвращает , если поиск успешен.
Например:
Обратите внимание, что методы используют строгое сравнение. Таким образом, если мы ищем , он находит именно , а не ноль
Если мы хотим проверить наличие элемента, и нет необходимости знать его точный индекс, тогда предпочтительным является .
Кроме того, очень незначительным отличием является то, что он правильно обрабатывает в отличие от :
Представьте, что у нас есть массив объектов. Как нам найти объект с определённым условием?
Здесь пригодится метод arr.find.
Его синтаксис таков:
Функция вызывается по очереди для каждого элемента массива:
- – очередной элемент.
- – его индекс.
- – сам массив.
Если функция возвращает , поиск прерывается и возвращается . Если ничего не найдено, возвращается .
Например, у нас есть массив пользователей, каждый из которых имеет поля и . Попробуем найти того, кто с :
В реальной жизни массивы объектов – обычное дело, поэтому метод крайне полезен.
Обратите внимание, что в данном примере мы передаём функцию , с одним аргументом. Это типично, дополнительные аргументы этой функции используются редко
Метод arr.findIndex – по сути, то же самое, но возвращает индекс, на котором был найден элемент, а не сам элемент, и , если ничего не найдено.
Метод ищет один (первый попавшийся) элемент, на котором функция-колбэк вернёт .
На тот случай, если найденных элементов может быть много, предусмотрен метод arr.filter(fn).
Синтаксис этого метода схож с , но возвращает массив из всех подходящих элементов:
Например:
Строковые методы, поиск и замена
Следующие методы работают с регулярными выражениями из строк.
Все методы, кроме replace, можно вызывать как с объектами типа regexp в аргументах, так и со строками, которые автоматом преобразуются в объекты RegExp.
Так что вызовы эквивалентны:
var i = str.search(/\s/) var i = str.search("\\s")
При использовании кавычек нужно дублировать \ и нет возможности указать флаги. Если регулярное выражение уже задано строкой, то бывает удобна и полная форма
var regText = "\\s" var i = str.search(new RegExp(regText, "g"))
Возвращает индекс регулярного выражения в строке, или -1.
Если Вы хотите знать, подходит ли строка под регулярное выражение, используйте метод (аналогично RegExp-методы ). Чтобы получить больше информации, используйте более медленный метод (аналогичный методу ).
Этот пример выводит сообщение, в зависимости от того, подходит ли строка под регулярное выражение.
function testinput(re, str){ if (str.search(re) != -1) midstring = " contains "; else midstring = " does not contain "; document.write (str + midstring + re.source); }
Если в regexp нет флага , то возвращает тот же результат, что .
Если в regexp есть флаг , то возвращает массив со всеми совпадениями.
Чтобы просто узнать, подходит ли строка под регулярное выражение , используйте .
Если Вы хотите получить первый результат — попробуйте r.
В следующем примере используется, чтобы найти «Chapter», за которой следует 1 или более цифр, а затем цифры, разделенные точкой. В регулярном выражении есть флаг , так что регистр будет игнорироваться.
str = "For more information, see Chapter 3.4.5.1"; re = /chapter (\d+(\.\d)*)/i; found = str.match(re); alert(found);
Скрипт выдаст массив из совпадений:
- Chapter 3.4.5.1 — полностью совпавшая строка
- 3.4.5.1 — первая скобка
- .1 — внутренняя скобка
Следующий пример демонстрирует использование флагов глобального и регистронезависимого поиска с . Будут найдены все буквы от А до Е и от а до е, каждая — в отдельном элементе массива.
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var regexp = //gi; var matches = str.match(regexp); document.write(matches); // matches =
Метод replace может заменять вхождения регулярного выражения не только на строку, но и на результат выполнения функции. Его полный синтаксис — такой:
var newString = str.replace(regexp/substr, newSubStr/function)
- Объект RegExp. Его вхождения будут заменены на значение, которое вернет параметр номер 2
- Строка, которая будет заменена на .
- Строка, которая заменяет подстроку из аргумента номер 1.
- Функция, которая может быть вызвана для генерации новой подстроки (чтобы подставить ее вместо подстроки, полученной из аргумента 1).
Метод не меняет строку, на которой вызван, а просто возвращает новую, измененную строку.
Чтобы осуществить глобальную замену, включите в регулярное выражение флаг .
Если первый аргумент — строка, то она не преобразуется в регулярное выражение, так что, например,
var ab = "a b".replace("\\s","..") // = "a b"
Вызов replace оставил строку без изменения, т.к искал не регулярное выражение , а строку «\s».
В строке замены могут быть такие спецсимволы:
Pattern | Inserts |
Вставляет «$». | |
Вставляет найденную подстроку. | |
Вставляет часть строки, которая предшествует найденному вхождению. | |
Вставляет часть строки, которая идет после найденного вхождения. | |
or | Где или — десятичные цифры, вставляет подстроку вхождения, запомненную -й вложенной скобкой, если первый аргумент — объект RegExp. |
Если Вы указываете вторым параметром функцию, то она выполняется при каждом совпадении.
В функции можно динамически генерировать и возвращать строку подстановки.
Первый параметр функции — найденная подстрока. Если первым аргументом является объект , то следующие параметров содержат совпадения из вложенных скобок. Последние два параметра — позиция в строке, на которой произошло совпадение и сама строка.
Например, следующий вызов возвратит XXzzzz — XX , zzzz.
function replacer(str, p1, p2, offset, s) { return str + " - " + p1 + " , " + p2; } var newString = "XXzzzz".replace(/(X*)(z*)/, replacer)
Как видите, тут две скобки в регулярном выражении, и потому в функции два параметра , .
Если бы были три скобки, то в функцию пришлось бы добавить параметр .
Следующая функция заменяет слова типа на :
function styleHyphenFormat(propertyName) { function upperToHyphenLower(match) { return '-' + match.toLowerCase(); } return propertyName.replace(//, upperToHyphenLower); }
Итерируемые объекты и псевдомассивы
Есть два официальных термина, которые очень похожи, но в то же время сильно различаются. Поэтому убедитесь, что вы как следует поняли их, чтобы избежать путаницы.
- Итерируемые объекты – это объекты, которые реализуют метод , как было описано выше.
- Псевдомассивы – это объекты, у которых есть индексы и свойство , то есть, они выглядят как массивы.
При использовании JavaScript в браузере или других окружениях мы можем встретить объекты, которые являются итерируемыми или псевдомассивами, или и тем, и другим.
Например, строки итерируемы (для них работает ) и являются псевдомассивами (они индексированы и есть ).
Но итерируемый объект может не быть псевдомассивом. И наоборот: псевдомассив может не быть итерируемым.
Например, объект из примера выше – итерируемый, но не является псевдомассивом, потому что у него нет индексированных свойств и .
А вот объект, который является псевдомассивом, но его нельзя итерировать:
Что у них общего? И итерируемые объекты, и псевдомассивы – это обычно не массивы, у них нет методов , и т.д. Довольно неудобно, если у нас есть такой объект и мы хотим работать с ним как с массивом. Например, мы хотели бы работать с , используя методы массивов. Как этого достичь?
Статичные регэкспы
В некоторых реализациях javascript регэкспы, заданные коротким синтаксисом /…/ — статичны. То есть, такой объект создается один раз в некоторых реализациях JS, например в Firefox. В Chrome все ок.
function f() { // при многократных заходах в функцию объект один и тот же var re = /lalala/ }
По стандарту эта возможность разрешена ES3, но запрещена ES5.
Из-за того, что при глобальном поиске меняется, а сам объект регэкспа статичен, первый поиск увеличивает , а последующие — продолжают искать со старого , т.е. могут возвращать не все результаты.
При поиске всех совпадений в цикле проблем не возникает, т.к. последняя итерация (неудачная) обнуляет .
includes, startsWith, endsWith
Следующие три
метода позволяют проверять: есть ли в строке искомая подстрока. Первый метод
имеет ожидаемый синтаксис:
str.includes(substr)
он возвращает 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
indexOf
Как и метод , метод использует строгое сравнение, а не функцию как метод . Однако, в отличие от , он возвращает индекс элемента, а не логическое значение. Вы также можете указать, с какого индекса массива можно начать поиск.
Я считаю очень полезным методом. Это быстрый и удобный метод, позволяющий узнать, существует ли элемент в массиве, и где именно в массиве он находится. Как он показывает, существует ли элемент? Если он возвращает положительное число, мы знаем, что элемент существует, а если он возвращает значение -1, мы понимаем, что такого элемента нет.
Как видите, хотя мы могли бы получить эту же информацию с помощью методов или , здесь нам нужно писать намного меньше кода. Нам не нужно писать функцию для сравнения, поскольку она уже входит в метод .
Как и другие методы, возвращает индекс первого найденного совпадающего элемента. JavaScript позволяет использовать альтернативный метод массива, . Как вы можете догадаться, он делает то же, что и метод , но начинает с последнего индекса массива и движется назад. Также вы можете указать второй параметр, но помните, что индексы не меняются просто потому, что вы используете другой метод.
substr
Метод substr похож на substring и JS slice тем, что выбирает часть строки и возвращает новую. Но вместо того, чтобы указывать начало и конец выбранного отрывка, мы указываем начало отрывка и длину возвращаемой подстроки.
Начальная позиция может быть отрицательной, в таком случае указывается количество символов с конца строки. Если второй аргумент опущен, будут извлечены все символы до конца строки.
Этот метод и поддерживается большим количеством браузеров, но он не стандартизирован в ECMAScript и во многих источниках указывается как устаревший.
Следующий пример демонстрирует использование метода substr для достижения результатов, аналогичных применению методов slice и substring:
var str = 'невероятно'; var str2 = str.substr(2); console.log(str2); // вероятно // аргументы: начальный индекс, длина var str3 = str.substr(2, 2); console.log(str3); // ве // отсчёт с конца строки var str4 = str.substr(-4); console.log(str4); // ятно var str5 = str.substr(-4, 2); console.log(str5); // ят
Данная публикация является переводом статьи «JavaScript slice and Other Substring Methods» , подготовленная редакцией проекта.
Две стадии преобразования
Итак, объект преобразован в примитив при помощи или .
Но на этом преобразования не обязательно заканчиваются. Вполне возможно, что в процессе вычислений этот примитив будет преобразован во что-то другое.
Например, рассмотрим применение к объекту операции :
Объект был сначала преобразован в примитив, используя численное преобразование, получилось .
Далее, так как значения всё ещё разных типов, применяются правила преобразования примитивов, результат: .
То же самое – при сложении с объектом при помощи :
Или вот, для разности объектов:
Исключение:
Объект по историческим причинам является исключением.
Бинарный оператор плюс обычно использует численное преобразование и метод . Как мы уже знаем, если подходящего нет (а его нет у большинства объектов), то используется , так что в итоге преобразование происходит к строке. Но если есть , то используется . Выше в примере как раз это демонстрируют.
У объектов есть и – возвращает количество миллисекунд, и – возвращает строку с датой.
…Но оператор для использует именно (хотя должен бы ).
Это и есть исключение:
Других подобных исключений нет.
Как испугать Java-разработчика
В языке Java (это не JavaScript, другой язык, здесь приведён для примера) логические значения можно создавать, используя синтаксис , например .
В JavaScript тоже есть подобная возможность, которая возвращает «объектную обёртку» для логического значения.
Эта возможность давно существует лишь для совместимости, она и не используется на практике, поскольку приводит к странным результатам. Некоторые из них могут сильно удивить человека, не привыкшего к JavaScript, например:
Почему запустился ? Ведь в находится … Проверим:
Дело в том, что – это не примитивное значение, а объект. Поэтому в логическом контексте он преобразуется к , в результате работает первый пример.
А второй пример вызывает , который преобразует объект к строке, и он становится .
В JavaScript вызовы не используются, а используются простые вызовы соответствующих функций, они преобразуют значение в примитив нужного типа, например .
Свойство Access
ECMAScript 5 (2009) разрешает свойство access для строк:
Пример
var str = «HELLO WORLD»;
str; // возвращает H
Свойство access может быть немного непредсказуемым:
- Это не работает в Internet Explorer 7 или более ранней версии
- Это делает строки похожими на массивы (но это не так)
- Если символ не найден, [] возвращает undefined, а charAt() возвращает пустую строку.
- Это только для чтения. str = «A» не выдаёт ошибок (но не работает!)
Пример
var str = «HELLO WORLD»;
str = «A»;
// Не выдаёт ошибки, но не работает
str; // возвращает H
Если вы хотите работать со строкой в виде массива, вы можете преобразовать её в массив.
Некоторые другие методы
У строковых переменных
есть еще пара полезных и часто используемых методов, это:
str.trim()
убирает пробелы
в начале и конце строки:
let str = " string "; console.log( str.trim() );
И
str.repeat(n)
для повторения
строки n раз:
let str = "Abc"; console.log( str.repeat(5) );
Это, конечно, не
все методы строк. По мере использования JavaScript вы познакомитесь
со многими другими, но для начала этого будет достаточно. Также отдельно стоит
тема регулярных выражений – мощнейший инструмент для поиска, замены и проверки различных
строковых шаблонов, но об этом мы будем говорить на отдельном занятии.
Видео по теме
JavaScipt #1: что это такое, с чего начать, как внедрять и запускать
JavaScipt #2: способы объявления переменных и констант в стандарте ES6+
JavaScript #3: примитивные типы number, string, Infinity, NaN, boolean, null, undefined, Symbol
JavaScript #4: приведение типов, оператор присваивания, функции alert, prompt, confirm
JavaScript #5: арифметические операции: +, -, *, /, **, %, ++, —
JavaScript #6: условные операторы if и switch, сравнение строк, строгое сравнение
JavaScript #7: операторы циклов for, while, do while, операторы break и continue
JavaScript #8: объявление функций по Function Declaration, аргументы по умолчанию
JavaScript #9: функции по Function Expression, анонимные функции, callback-функции
JavaScript #10: анонимные и стрелочные функции, функциональное выражение
JavaScript #11: объекты, цикл for in
JavaScript #12: методы объектов, ключевое слово this
JavaScript #13: клонирование объектов, функции конструкторы
JavaScript #14: массивы (array), методы push, pop, shift, unshift, многомерные массивы
JavaScript #15: методы массивов: splice, slice, indexOf, find, filter, forEach, sort, split, join
JavaScript #16: числовые методы toString, floor, ceil, round, random, parseInt и другие
JavaScript #17: методы строк — length, toLowerCase, indexOf, includes, startsWith, slice, substring
JavaScript #18: коллекции Map и Set
JavaScript #19: деструктурирующее присваивание
JavaScript #20: рекурсивные функции, остаточные аргументы, оператор расширения
JavaScript #21: замыкания, лексическое окружение, вложенные функции
JavaScript #22: свойства name, length и методы call, apply, bind функций
JavaScript #23: создание функций (new Function), функции setTimeout, setInterval и clearInterval
Свойства строк
Свойство | Описание | |
---|---|---|
constructor | возвращает функцию-конструктор строки | |
var str = «Hello world!»;
|
||
length | возвращает длину (количество символов) строки | |
var str = «Hello world!»;
|
||
prototype | позволяет добавить свойства и методы к объекту (если строка — объект) | |
function student(name, surname, faculty) {
|