Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Быстрый 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 2009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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) 2009

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

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

realsonic.moikrug.ru 2009

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

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

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

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

Meettya (meettya.pip.verisignlabs.com) 2009

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

Meettya (meettya.pip.verisignlabs.com) 2009

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

rews 2011

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

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

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

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