Быстрый trim для JavaScript

Самый быстрый trim на JavaScript выглядит странно:

function trim12 (str) {
    var	str = str.replace(/^\s\s*/, ''),
        ws = /\s/,
        i = str.length;
    while (ws.test(str.charAt(--i)));
    return str.slice(0, i + 1);
}

Код взят из блога Flagrant Badassery. Цикл с регуляркой быстрее, чем простое регулярное выражение /\s+$/, а кроме того, \s\s* быстрее, чем \s+? OMG!

Поделиться
Отправить
13 комментариев
baka.name

Регулярные выражения — это же не магия, а конечные автоматы. ^_^

Цикл с регуляркой быстрее, чем простое регулярное выражение /\s+$/

Это вполне понятно — цикл делает только то, что надо — сравнивает с «пробельным классом символов» по одному символы, начиная с  конца строки, пока они есть.
А «простое регулярное выражение» начинает сопоставляться с каждого «пробельного» символа, начиная с начала строки, потом обламывается, не обнаружив конца строки после пробелов (если их было несколько подряд — то всё равно пытается проделать то же самое начиная со второго из них, и т. д...).

а кроме того, \s\s* быстрее, чем \s+

Это не столь очевидно, правда, напоминает фридловскую «развёртку регекспа», но сейчас не помню, почему она эффективнее.
(И не понимаю, почему оно эффективнее _здесь_. -_-’)

Азат Разетдинов (razetdinov.ya.ru)

«Простое» регулярное выражение спотыкается на каждом пробеле, пока дойдёт до конца строки; приведённый код сразу идёт в конец и ищет пробелы перед ним.

Евгений Степанищев (bolknote.ru)

Комментарий для razetdinov.ya.ru:

Движки регулярок сильно оптимизируются. \s+$ вполне можно соптимизировать как «начать цикл с конца, если не пробел, остановиться». Я не смотрел в код, но даже не сомневаюсь, что libprce именно так и делает.

Евгений Степанищев (bolknote.ru)

Комментарий для baka.name:

Я понимаю, что это не магия. Но я ожидал от движков регулярных выражений в JS большей оптимизированности. \s\s* просто обнажает недостатки этих движков.

Евгений Степанищев (bolknote.ru)

Комментарий для razetdinov.ya.ru:

«Если не пробел» читать как «если не пробельный символ».

Азат Разетдинов (razetdinov.ya.ru)

Комментарий для Евгения Степанищева:

http://pcre.org/pcre.txt
“Consider a simple pattern such as ‘abcd$’ when applied to  a  long string that does not match. Because matching proceeds from left to right, PCRE will look for each «a» in the subject and then see if what follows matches the rest of the pattern.”

Евгений Степанищев (bolknote.ru)

Комментарий для razetdinov.ya.ru:

Как всё плохо-то :(

realsonic.moikrug.ru

У браузеров разные движки, вроде бы? Насколько я знаю, Firefox и Chrome используют какие-то новые разработки, компилируемый JS.

Евгений Степанищев (bolknote.ru)

Комментарий для realsonic.moikrug.ru:

Разные, конечно. Но оптимизация regexp, видимо, находится в удручающем состоянии у всех.

Meettya (meettya.pip.verisignlabs.com)

Суть проблемы в том, что для JavaScript строка одним куском — по сути join массива.
Соответственно — методы массива на большом массиве работают быстрее, чем литеральная его обработка после join.
Ведь str.charAt(-​-​i)=str[-​-​i]
Так и получается, когда «все есть объект».

Meettya (meettya.pip.verisignlabs.com)

Т. е. смысл в том, что сама по себе задача решается для «сферического коня в вакууме».
Я на стопяцот процентов уверен, что «откуси» он достаточный кусок СНАЧАЛА и с КОНЦА и обработай оба одной и той же регуляркой /^\s+|\s+$/ а потом слепи он это обратно — будет не медленнее его конечного варианта. Но так же извратно по сути. :)

rews

Регулярные выражения javascript
http://forjoomla.ru/regulyarnie-virajeniya-javascript.html

Евгений Степанищев (bolknote.ru)

Комментарий для rews:

Простите, но чем эта статья лучше 100500 других куцых статей на ту же тему?

Популярное