Строки, несомненно, являются одним из самых важных типов данных в любом языке программирования.

Строки есть практически в каждом языке программирования, и научиться их эффективному использованию — основная необходимость каждого разработчика. Чтобы эффективно работать со строками, разработчик должен понимать регулярные выражения, поскольку они могут манипулировать строками. С 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 г.