Строки, несомненно, являются одним из самых важных типов данных в любом языке программирования.
Строки есть практически в каждом языке программирования, и научиться их эффективному использованию — основная необходимость каждого разработчика. Чтобы эффективно работать со строками, разработчик должен понимать регулярные выражения, поскольку они могут манипулировать строками. С ECMAScript 6 строки и регулярные выражения теперь имеют новые функции и те недостающие функции, которые есть в других языках программирования.
В этом посте я перечислю несколько новых фич/методов работы со строками из ES6:
UTF-16
Кодовые точки
До ECMAScript 6 строки JavaScript поддерживали только 16-битную кодировку символов. Все строковые свойства и методы, такие как длина и метод charAt()
, были основаны на этих 16-битных единицах кода. Хотя раньше для хранения любого символа было достаточно 16 бит, но теперь ES6 представила новый набор символов Unicode.
Первые 2¹⁶ кодовые точки в UTF-16 представлены как отдельные 16-битные кодовые единицы. Этот диапазон называется Базовая многоязычная плоскость (BMP). Все после этого считается находящимся в одной из дополнительных плоскостей, где кодовые точки не могут быть представлены всего лишь 16-битами. Для решения этой проблемы в UTF-16 введены суррогатные пары, в которых одна кодовая точка представлена двумя 16-битными кодовыми единицами. Это означает, что любой отдельный символ в строке может быть либо одной кодовой единицей для символов BMP, что дает в общей сложности 16 бит, либо двумя единицами для дополнительных символов плоскости, что дает в общей сложности 32 бита.
Это означает, что все строковые операции работают с 16-битной кодовой единицей в ECMAScript 5, вы можете получить неожиданные результаты из кодовых строк UTF-16:
var text = "𠮷"; console.log(text.length); // 2 console.log(/^.$/.test(text)); // false console.log(text.charAt(0)); // "" console.log(text.charAt(1)); // "" console.log(text.charCodeAt(0)); // 55362 console.log(text.charCodeAt(1)); // 57271
Единственный символ Unicode 𠮷
представлен с помощью суррогатных пар, поэтому строковая операция JavaScript обрабатывает его как два 16-битных символа. Это означает:
length
переменнойtext
равно2
, хотя должно быть1
.- Когда мы пытаемся с помощью регулярного выражения сопоставить один символ, это не удается, потому что он думает, что есть два символа.
- Метод
charAt()
не может вернуть допустимую строку символов, поскольку ни один набор из 16 битов не соответствует печатному символу. - Метод
charCodeAt()
также не может правильно идентифицировать символ и возвращает соответствующее 16-битное число для каждой единицы кода.
С другой стороны, ES6 применяет кодировку строк UTF-16 для решения подобных проблем. Стандартизация строковых операций, основанная на этой кодировке символов, означает, что JavaScript может поддерживать функции, предназначенные специально для работы с суррогатными парами.
Метод codePointAt()
Для полной поддержки UTF-16 в ES6 добавлен новый метод с именем codePointAt()
. Этот метод извлекает кодовую точку Unicode в заданную позицию в строке. Вместо позиции символа этот метод использует позицию единицы кода и возвращает целое число.
var text = "𠮷a"; console.log(text.charCodeAt(0)); // 55362 console.log(text.charCodeAt(1)); // 57271 console.log(text.charCodeAt(2)); // 97 console.log(text.codePointAt(0)); // 134071 console.log(text.codePointAt(1)); // 57271 console.log(text.codePointAt(2)); // 97
Метод codePointAt()
возвращает то же значение при работе с символами BMP, но в нашем случае первый символ в переменной text
не является BMP, поэтому он воспринимается как две единицы кода и возвращает свойство длины как 3 вместо 2. Метод charCodeAt()
возвращает код только для первой позиции в 0
. Но метод codePointAt()
возвращает единицу кода для всех символов в строке. Хотя оба метода возвращают одно и то же значение для позиции 1 & 2
.
Вы также можете создать функцию, чтобы узнать, имеют ли символы в строке две кодовые точки или примечание:
function is32Bit(c) { return c.codePointAt(0) > 0xFFFF; } console.log(is32Bit("𠮷")); // true console.log(is32Bit("a")); // false
Примечание. 0xFFFF представляет собой шестнадцатеричные символы, поэтому любая кодовая точка, превышающая ее, будет состоять из двух кодовых точек.
Метод String.fromCodePoint()
Метод String.fromCodePoint()
прямо противоположен методу codePointAt()
. Приведенный выше метод codePointAt()
возвращает единицу кодовой точки для любого заданного символа в строке, а String.fromCodePoint()
возвращает одну строку символов из заданной кодовой точки.
console.log(String.fromCodePoint(134071)); // "𠮷"
В ECMAScript 5 у нас был метод String.fromCharCode()
, который отлично работал для символов BMP, поэтому в ECMAScript 6 теперь у нас есть метод String.fromCodePoint()
для всех символов, отличных от BMP.
Метод normalize()
В Юникоде разные символы могут считаться эквивалентными при сравнении двух строк или любых других операций, основанных на сравнении. Есть два способа определить это: 1) каноническая эквивалентность и 2) совместимость.
- Каноническая эквивалентность означает, что две последовательности кодовых точек можно считать взаимозаменяемыми.
- Совместимость означает, что любые две совместимые последовательности кодовых точек выглядят по-разному, но могут использоваться взаимозаменяемо в определенных случаях.
Например: две строки, представляющие один и тот же текст, могут содержать разные единицы кода. например: «æ» и «ae». Первый - это строка из одного символа, а второй - строка из двух символов. Они оба могут использоваться взаимозаменяемо, но они не эквивалентны, если не нормализованы каким-либо образом.
ES6 поддерживает нормализацию Unicode, предоставляя строки методу normalize()
. Этот метод дополнительно принимает один строковый параметр, указывающий одну из следующих форм нормализации Unicode для применения:
- Каноническая композиция формы нормализации (
"NFC"
), которая используется по умолчанию. - Каноническая декомпозиция формы нормализации (
"NFD"
) - Композиция совместимости форм нормализации (
"NFKC"
) - Разложение совместимости форм нормализации (
"NFKD"
)
Вы можете узнать больше о вышеуказанных формах на веб-странице Юникода.
Нам просто нужно убедиться, что при сравнении строк обе строки должны быть нормализованы к одной и той же форме.
var normalized = values.map(function(text) { return text.normalize(); }); normalized.sort(function(first, second) { if (first < second) { return -1; } else if (first === second) { return 0; } else { return 1; } });
Этот приведенный выше код преобразует строки в массив в нормализованную форму, чтобы массив можно было отсортировать соответствующим образом. В приведенном выше коде мы нормализовали первую и вторую строку по методу нормализации по умолчанию, но вы также можете использовать любую форму для нормализации строк.
values.sort(function(first, second) { var firstNormalized = first.normalize("NFD"), secondNormalized = second.normalize("NFD"); if (firstNormalized < secondNormalized) { return -1; } else if (firstNormalized === secondNormalized) { return 0; } else { return 1; } });
Хотя метод normalize()
очень полезен при сравнении строк, он вам, вероятно, не понадобится, если только вы не работаете с интернационализированным приложением.
Определить подстроки
До ECMAScript 5 для поиска подстрок любой строки/текста мы использовали метод indexOf
. В ECMAScript 6 теперь у нас есть три новых метода, которые упрощают поиск подстрок:
1) includes()
: возвращает true, если заданный текст найден где-либо в строке, иначе возвращается false.
2) startsWith()
: возвращает true, если заданный текст находится в начале строки, иначе вернет false.
3) endsWith()
: вернет true, если заданный текст будет найден в конце строки, иначе вернет false.
Каждый из трех вышеприведенных методов принимает два параметра. Первый — это символ, который вы хотите найти в строке, а второй — необязательный порядковый номер. Если указано, метод начнет поиск символа из этого индекса, кроме метода endsWith()
. Если необязательный номер индекса передается с помощью метода endsWith()
, он начнет сопоставляться с конца до индекса. Если второй аргумент опущен, startsWith()
и includes()
начинаются с начала строки, а endsWith()
начинаются с конца строки.
var msg = "Hello world!"; console.log(msg.startsWith("Hello")); // true console.log(msg.endsWith("!")); // true console.log(msg.includes("o")); // true console.log(msg.startsWith("o")); // false console.log(msg.endsWith("world!")); // true console.log(msg.includes("x")); // false console.log(msg.startsWith("o", 4)); // true console.log(msg.endsWith("o", 8)); // true console.log(msg.includes("o", 8)); // false
Как видно из приведенных выше примеров, все три метода возвращают boolean
результатов. Если вы хотите найти фактическую позицию символа в строке, вам нужно использовать методы indexOf()
и lastIndexOf()
.
Метод repeat()
ECMAScript 6 включает этот новый метод для строки, который принимает число в качестве параметра. Метод repeat()
будет использовать это число для повторения строки и даст нам новую строку.
console.log("Hello".repeat(2)); // "HelloHello" console.log("World".repeat(3)); // "WorldWorldWorld" console.log("Hello World".repeat(3)); // "Hello WorldHello WorldHello World"
Это очень удобный и полезный метод, особенно при работе с текстом.
// indent using a specified number of spaces var indent = " ".repeat(4), indentLevel = 0; // whenever you increase the indent var newIndent = indent.repeat(++indentLevel);
Первый экземпляр repeat()
создает строку из четырех пробелов, а переменная indentLevel
отслеживает уровень indent
. Затем вы можете просто вызвать repeat()
с увеличенным indentLevel
, чтобы изменить количество пробелов.
Я рассмотрел почти все, что связано со строками. Я объясню регулярное выражение и шаблонный литерал в следующих двух постах.
Первоначально опубликовано на ashishuideveloper.in 12 ноября 2018 г.