Книга: Выразительный JavaScript

Жадность

Жадность

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

function stripComments(code) {
  return code.replace(///.*|/*[^]**//g, "");
}
console.log(stripComments("1 + /* 2 */3"));
// ? 1 + 3
console.log(stripComments("x = 10;// ten!"));
// ? x = 10;
console.log(stripComments("1 /* a */+/* b */ 1"));
// ? 1  1

Часть перед оператором «или» совпадает с двумя слэшами, за которыми идёт любое количество символов, кроме символов перевода строки. Часть, убирающая многострочные комментарии, более сложна. Мы используем , т. е. любой символ, не являющийся пустым, в качестве способа найти любой символ. Мы не можем использовать точку, потому что блочные комментарии продолжаются и на новой строке, а символ перевода строки не совпадает с точкой.

Но вывод предыдущего примера неправильный. Почему?

Часть сначала попытается захватить столько символов, сколько может. Если из-за этого следующая часть регулярки не найдёт себе совпадения, произойдёт откат на один символ и попробует снова. В примере, алгоритм пытается захватить всю строку, и затем откатывается. Откатившись на четыре символа назад, он найдёт в строчке / — а это не то, чего мы добивались. Мы-то хотели захватить только один комментарий, а не пройти до конца строки и найти последний комментарий.

Из-за этого мы говорим, что операторы повторения (+, *, ?, and {}) жадные, то есть они сначала захватывают, сколько могут, а потом идут назад. Если вы поместите вопрос после такого оператора (+?, *?, ??, {}?), они превратятся в нежадных, и начнут находить самые маленькие из возможных вхождений.

И это то, что нам нужно. Заставив звёздочку находить совпадения в минимально возможном количестве символов строчки, мы поглощаем только один блок комментариев, и не более того.

function stripComments(code) {
  return code.replace(///.*|/*[^]*?*//g, "");
}
console.log(stripComments("1 /* a */+/* b */ 1"));
// ? 1 + 1

Множество ошибок возникает при использовании жадных операторов вместо нежадных. При использовании оператора повтора сначала всегда рассматривайте вариант нежадного оператора.

Оглавление книги


Генерация: 0.769. Запросов К БД/Cache: 2 / 0
поделиться
Вверх Вниз