Кога се компилират литералите на регулярни изрази на JavaScript

Според Ръководството за RegExp на MDN литералите на регулярните изрази се компилират, докато RegExp обектите, създадени чрез извикване на конструктора, не са.

Въпросът ми е сега, кога се провежда компилацията? Тъй като литералът има уникален синтаксис, той се идентифицира като регулярен израз по време на анализ. Това би направило възможно компилирането му веднъж и повторното използване на резултата всеки път, когато бъде оценен, в резултат на което двата примера имат (почти) еднаква скорост.

var str = "Hello World";

// Example 1
var regExp1 = /[aeiou]+/gi;
for(var i = 0; i < 1000; ++i)
    regExp1.exec(str);

// Example 2
for(var j = 0; j < 1000; ++j)
    /[aeiou]+/gi.exec(str);

Някакви идеи дали това се използва на практика от някоя JavaScript машина?


person Johannes Matokic    schedule 23.01.2014    source източник
comment
Не съм сигурен как тествате скоростта, но има JSPerf: jsperf.com/testing-regexp-define   -  person epascarello    schedule 23.01.2014


Отговори (1)


В документите на MDN ясно се посочва, че:

Литералната нотация осигурява компилация на регулярния израз, когато изразът се оценява.

и

Конструкторът на обекта на регулярен израз, например new RegExp("ab+c"), осигурява компилация по време на изпълнение на регулярния израз

Тестът, който направихте, не е много ясен. Къде измервате ефективността? Ето как виждам, че трябва да бъдат направени:

start = new Date();
for(var j = 0; j < 1000000; ++j)
    /[aeiou]+/gi.exec(str);
console.log(new Date - start);

start = new Date();
regex = new RegExp("[aeiou]+", "gi");
for(var j = 0; j < 1000000; ++j)
    regex.exec(str);
console.log(new Date - start);

Това произвежда:

147
118

Ясно е, че конструкторът е по-бърз от моите тестове (Chrome)

Освен това във вашия тест изобщо не сте тествали конструктора. Просто присвоявахте литерала в първия тест на име на променлива. По принцип тестовете бяха идентични.

person tsikov    schedule 30.03.2014
comment
Така че оптимизация като еднократна оценка и повторно използване чрез анализатора е малко вероятно да бъде приложена, тъй като нарушава спецификацията според MDN. - person Johannes Matokic; 15.05.2014
comment
От друга страна изглежда, че изобщо не е необходимо. Тествах с по-сложни изрази и времето за компилиране е малко в сравнение с времето, необходимо за съвпадение (поне за Firefox 29). Така че човек може да направи кода по-четлив, като посочи регулярния израз вътре в цикъла, ако има много използвани регулярни изрази. - person Johannes Matokic; 15.05.2014
comment
Трябва също да тества извикването на конструктора вътре в цикъла. Не можете да създадете пълния обект на регулярен израз, но можете да анализирате и компилирате регулярния израз, без да създавате действителния обект за времето за изпълнение. Това би било по-бързо от липсата на оптимизиране, но по-бавно от първия тест. Тъй като е литерал, компилираната версия е статична. - person Jamie Pate; 22.08.2014
comment
MDN Guide изрично препоръчва използването на литерали. Литералите на регулярния израз осигуряват компилация на регулярния израз, когато скриптът е зареден. Когато регулярният израз ще остане постоянен, използвайте това за по-добра производителност. Кое е това? - person toniedzwiedz; 12.02.2016