Co se pokazilo JavaScript RegExp API a jak to opravit

Během posledních několika let jsem příležitostně komentoval JavaScriptové RegExp API, syntaxi a chování na ES-Discuss mailing listu. Nedávno vynálezce JavaScriptu Brendan Eich navrhl, abych v zájmu rozproudění diskuse sepsal seznam změn regulárních výrazů, které je třeba vzít v úvahu pro budoucí standardy ECMAScript (nebo, jak to vtipně řekl, mít svých „95 [regulárních] tezí přibitých na Dveře katedrály ES3“). Myslel jsem, že to zkusím, ale svou odpověď rozdělím do několika částí. V tomto příspěvku budu diskutovat o problémech s aktuálním RegExp API a chováním. Nechám stranou nové funkce, které bych rád přidal, a pouze navrhnu způsoby, jak stávající funkce vylepšit. O možných nových funkcích budu diskutovat v následném příspěvku.

U jazyka tak široce používaného, ​​jako je JavaScript, musí jakýkoli realistický návrh změny silně zvážit zpětnou kompatibilitu. Z tohoto důvodu některé z následujících návrhů nemusí být obzvláště realistický, ale přesto si myslím, že a ) stojí za to zvážit, co by se mohlo změnit, pokud by zpětná kompatibilita nebyla problémem, a b ) z dlouhodobého hlediska by všechny tyto změny zlepšily snadnost použití a předvídatelnost fungování regulárních výrazů v JavaScriptu.

Odeberte RegExp.prototype.lastIndex a nahraďte jej argumentem pro počáteční pozici

Skutečný návrh:Ukončete podporu RegExp.prototype.lastIndex a přidejte argument "pos" do metod RegExp.prototype.exec/test

05 JavaScriptu vlastnost slouží příliš mnoha účelům najednou:

Umožňuje uživatelům ručně určit, kde začít hledání podle regulárního výrazu
Mohli byste tvrdit, že to není 17 's zamýšlený účel, ale je to přesto důležité použití, protože neexistuje žádná alternativní funkce, která by to umožňovala. 29 není v tomto úkolu příliš dobrý. Musíte zkompilovat svůj regulární výraz s 36 příznak nechat 46 být používán tímto způsobem; a dokonce i poté určuje pouze počáteční pozici pro 53 /61 metody. Nelze jej použít k nastavení počáteční pozice pro 76 /80 /93 /106 metody.
Označuje pozici, kde skončil poslední zápas
I když byste mohli odvodit koncovou pozici shody přidáním indexu shody a délky, toto použití 112 slouží jako pohodlný a běžně používaný doplněk k 125 vlastnost na odpovídajících polích vrácených 133 . Jako vždy pomocí 143 takto funguje pouze pro regulární výrazy kompilované s 158 .
Používá se ke sledování pozice, kde by mělo začít další vyhledávání
To přichází v úvahu například při použití regulárního výrazu k iteraci všech shod v řetězci. Nicméně skutečnost, že 166 je ve skutečnosti nastaveno na koncovou pozici poslední shody spíše než na pozici, kde by mělo začít další hledání (na rozdíl od ekvivalentů v jiných programovacích jazycích), způsobuje problém po shodách s nulovou délkou, které jsou snadno možné u regulárních výrazů jako 176 nebo 184 . Proto jste nuceni ručně zvýšit 198 v takových případech. O tomto problému jsem již dříve psal podrobněji (viz:Chyba IE lastIndex s nulovou délkou shod regulárního výrazu ), stejně jako Jan Goyvaerts (Pozor na zápasy s nulovou délkou ).

Bohužel 207 Všestrannost má za následek, že nefunguje ideálně pro žádné konkrétní použití. Myslím, že 212 je stejně špatně umístěn; pokud potřebujete uložit koncovou (nebo příští-start) pozici vyhledávání, měla by to být vlastnost cílového řetězce a ne regulárního výrazu. Zde jsou tři důvody, proč by to fungovalo lépe:

  • Umožnilo by vám to použít stejný regulární výraz s více řetězci, aniž byste ztratili přehled o další pozici vyhledávání v každém z nich.
  • Umožnilo by to používat více regulárních výrazů se stejným řetězcem a každý z nich by navázal od místa, kde skončil poslední.
  • Pokud hledáte dva řetězce se stejným regulárním výrazem, pravděpodobně neočekáváte, že hledání v druhém řetězci začne z libovolné pozice jen proto, že byla nalezena shoda v prvním řetězci.

Ve skutečnosti Perl používá tento přístup ukládání pozic dalšího hledání s řetězci s velkým efektem a přidává kolem něj různé funkce.

Takže to je můj případ pro 226 je špatně umístěn, ale jdu ještě dále v tom, že si nemyslím, že 231 by měl být v JavaScriptu vůbec zahrnut. Taktika Perlu funguje dobře pro Perl (zejména když je považována za kompletní balíček), ale některé další jazyky (včetně Pythonu) vám umožňují zadat počáteční pozici vyhledávání jako argument při volání metod regulárních výrazů, což je podle mého názoru přirozenější přístup. a snazší pro vývojáře k pochopení a použití. Proto bych opravil 242 tím, že se ho úplně zbavíte. Metody regulárního výrazu a metody řetězců používající regulární výraz by používaly interní sledovače pozic vyhledávání, které uživatel nepozoruje, a 251 a 263 metody by dostaly druhý argument (nazvaný 274 , pro pozici), která určuje, kde má začít hledání. Může být vhodné zadat také 287 metody 291 , 301 , 313 a 325 jejich vlastní 334 argumenty, ale to není tak důležité a funkce, které by poskytovaly, nejsou v současné době možné prostřednictvím 340 každopádně.

Níže jsou uvedeny příklady některých běžných použití 353 by mohl být přepsán, pokud byly provedeny tyto změny:

Začněte hledat od pozice 5 pomocí 366 (status quo):

var regexGlobal = /\w+/g,
    result;

regexGlobal.lastIndex = 5;
result = regexGlobal.test(str);
// must reset lastIndex or future tests will continue from the
// match-end position (defensive coding)
regexGlobal.lastIndex = 0;

var regexNonglobal = /\w+/;

regexNonglobal.lastIndex = 5;
// no go - lastIndex will be ignored. instead, you have to do this
result = regexNonglobal.test(str.slice(5));

Začněte hledat od pozice 5 pomocí 370 :

var regex = /\w+/, // flag /g doesn't matter
    result = regex.test(str, 5);

Iterace shody pomocí 384 :

var regex = /\w*/g,
    matches = [],
    match;

// the /g flag is required for this regex. if your code was provided a non-
// global regex, you'd need to recompile it with /g, and if it already had /g,
// you'd need to reset its lastIndex to 0 before entering the loop

while (match = regex.exec(str)) {
    matches.push(match);
    // avoid an infinite loop on zero-length matches
    if (regex.lastIndex == match.index) {
        regex.lastIndex++;
    }
}

Iterace shody pomocí 393 :

var regex = /\w*/, // flag /g doesn't matter
    pos = 0,
    matches = [],
    match;

while (match = regex.exec(str, pos)) {
    matches.push(match);
    pos = match.index + (match[0].length || 1);
}

Samozřejmě můžete snadno přidat svůj vlastní cukr pro další zjednodušení iterace shody, nebo by JavaScript mohl přidat metodu vyhrazenou pro tento účel podobnou Ruby's 401 (ačkoli JavaScript už to tak nějak má díky použití náhradních funkcí s 417 ).

Abych to zopakoval, popisuji, co bych dělal, kdyby byla zpětná kompatibilita irelevantní. Nemyslím si, že by bylo dobré přidat 428 argument do 439 a 448 kromě 459 vlastnost byla zastaralá nebo odstraněna z důvodu překrývání funkcí. Pokud 466 argument existoval, lidé by očekávali 475 být 486 když to není určeno. S 492 někdy pokazit toto očekávání by bylo matoucí a pravděpodobně by vedlo k latentním chybám. Pokud tedy 505 byla ukončena podpora ve prospěch 515 , měl by to být prostředek ke konci odstranění 528 celkem.

Odstranění neglobálního provozního režimu String.prototype.match

Skutečný návrh:Ukončete podporu String.prototype.match a přidejte novou metodu matchAll

538 aktuálně funguje velmi odlišně v závislosti na tom, zda 549 (globální) příznak byl nastaven na zadaný regulární výraz:

  • Pro regulární výrazy s 557 :Pokud nebyly nalezeny žádné shody, 562 je vrácen; jinak se vrátí pole jednoduchých shod.
  • Pro regulární výrazy bez 575 :584 metoda funguje jako alias 591 . Pokud shoda není nalezena, 607 je vrácen; jinak získáte pole obsahující (jedinou) shodu v klíči nula, se všemi zpětnými referencemi uloženými v následujících klíčích pole. Pole je také přiřazeno speciální 618 a 621 vlastnosti.

637 neglobální režim metody je matoucí a zbytečný. Důvod, proč je to zbytečné, je zřejmý:Pokud chcete funkcionalitu 648 , stačí jej použít (není potřeba alias). Je to matoucí, protože, jak je popsáno výše, 651 dva režimy metody vracejí velmi odlišné výsledky. Rozdíl není pouze v tom, zda získáte jeden zápas nebo všechny zápasy – získáte úplně jiný druh výsledku. A protože výsledkem je v obou případech pole, musíte znát stav 662 regulárního výrazu vlastnost, abyste věděli, se kterým typem pole máte co do činění.

Změnil bych 677 tím, že vždy vrátí pole obsahující všechny shody v cílovém řetězci. Také bych udělal, aby vracelo prázdné pole místo 689 , když nebyly nalezeny žádné shody (nápad, který pochází z knihovny base2 Deana Edwardse). Pokud chcete pouze první shodu nebo potřebujete zpětné reference a další podrobnosti o shodě, je to 697 je pro.

Bohužel, pokud chcete tuto změnu považovat za realistický návrh, vyžadovalo by to nějaký druh jazykové verze nebo přepnutí režimu 704 chování metody (myslím, že se to pravděpodobně nestane). Takže místo toho bych doporučil zavrhnout 719 metoda zcela ve prospěch nové metody (možná 724 ) se změnami předepsanými výše.

Zbavte se /g a RegExp.prototype.global

Skutečný návrh:Ukončete podporu /g a RegExp.prototype.global a do String.prototype.replace přidejte booleovský argument replaceAll

Pokud byly implementovány poslední dva návrhy a tedy 733 a 749 byly věci minulosti (nebo 755 již někdy nesloužil jako alias 769 ), jediná metoda, kde je 776 bude mít stále nějaký dopad je 787 . Navíc, ačkoli 792 navazuje na předchozí umění z Perlu atd., ve skutečnosti nedává smysl mít něco, co není atributem regulárního výrazu, uloženo jako příznak regulárního výrazu. Opravdu, 807 je spíše prohlášení o tom, jak chcete, aby metody aplikovaly svou vlastní funkčnost, a není neobvyklé chtít použít stejný vzor s 819 a bez něj (aktuálně byste k tomu museli vytvořit dva různé regulární výrazy). Kdyby to bylo na mně, zbavil bych se 828 příznak a jeho odpovídající 831 vlastnost a místo toho jednoduše zadejte 841 metoda další argument, který označuje, zda chcete nahradit pouze první shodu (výchozí zpracování) nebo všechny shody. To lze provést buď pomocí 855 boolean nebo pro lepší čitelnost 869 řetězec, který přijímá hodnoty 874 a 882 . Tento nový argument by měl další výhodu v tom, že by umožnil nahradit všechny funkce hledáním bez regulárního výrazu.

Všimněte si, že SpiderMonkey již má proprietární třetí 892 argument ("vlajky"), se kterým by byl tento návrh v rozporu. Pochybuji, že by tento konflikt způsobil velké pálení žáhy, ale v každém případě nový 904 argument by poskytoval stejnou funkcionalitu jako SpiderMonkey 917 argument je nejužitečnější pro (to znamená, že umožňuje globální nahrazení hledáním bez regulárního výrazu).

Změňte chování zpětných referencí na nezúčastněné skupiny

Skutečný návrh:Zpětné odkazy na nezúčastněné skupiny se neshodují

Zůstanu stručný, protože jsme s Davidem „lioreanem“ Anderssonem o to dříve argumentovali na ES-Discuss a jinde. David o tom podrobně psal na svém blogu (viz:ECMAScript 3 Regular Expressions:Specifikace, která nedává smysl ), a již jsem se toho dotkl zde (Regulární výrazy ECMAScript 3 jsou vadné již podle návrhu ). Při několika příležitostech Brendan Eich také prohlásil, že by rád viděl, aby se to změnilo. Krátké vysvětlení tohoto chování je, že v JavaScriptu jsou zpětné odkazy na zachycení skupin, které se (zatím) zápasu neúčastnily, vždy úspěšné (tj. shodují se s prázdným řetězcem), zatímco opak je pravdou ve všech ostatních variantách regulárních výrazů:selžou, a proto způsobí, že motor regulárních výrazů ustoupí nebo selže. Chování JavaScriptu znamená, že 920 vrátí 934 . (Negativní) důsledky toho sahají poměrně daleko při posouvání hranic regulárních výrazů.

Myslím, že všichni souhlasí s tím, že změna na tradiční chování zpětných odkazů by byla zlepšením – poskytuje mnohem intuitivnější ovládání, kompatibilitu s jinými příchutěmi regulárních výrazů a velký potenciál pro kreativní využití (např. viz můj příspěvek na Napodobování podmínek ). Větší otázkou je, zda by to bylo bezpečné ve světle zpětné kompatibility. Myslím, že by bylo, protože si představuji, že víceméně nikdo nepoužívá neintuitivní chování JavaScriptu záměrně. Chování JavaScriptu se rovná automatickému přidávání 942 kvantifikátor po zpětných referencích na nezúčastněné skupiny, což lidé již explicitně dělají, pokud skutečně chtějí, aby byly zpětné reference na podvzorce nenulové délky volitelné. Všimněte si také, že Safari 3.0 a dřívější nedodržovaly specifikace v tomto bodě a používaly intuitivnější chování, i když to se v novějších verzích změnilo (zejména tato změna byla způsobena zápisem na mém blogu spíše než zprávami o skutečných- světové chyby).

A konečně, pravděpodobně stojí za zmínku, že režim regulárního výrazu ECMAScript .NET (aktivovaný pomocí 954 flag) skutečně přepne .NET na nekonvenční chování zpětných odkazů ECMAScript.

Zajistěte, aby \d \D \w \W \b \B podporovalo Unicode (jako \s \S . ^ $, které již podporuje)

Skutečný návrh:Přidejte příznak /u (a odpovídající vlastnost RegExp.prototype.unicode), která mění význam \d, \w, \b a souvisejících tokenů

Porovnávání znaků s číslicemi a slovy s podporou Unicode není existující schopností JavaScriptu (nestačí vytvářet nestvůry znakových tříd, které jsou dlouhé stovky nebo tisíce znaků), a protože JavaScript postrádá pohled do pozadí, nemůžete reprodukovat hranici slova s ​​podporou Unicode. Dalo by se tedy říci, že tento návrh je mimo uvedený rozsah tohoto příspěvku, ale uvádím jej zde, protože to považuji spíše za opravu než za novou funkci.

Podle aktuálních standardů JavaScriptu 968 , 977 , 983 , 993 a 1009 používat interpretace mezera založené na Unicode a nový řádek , zatímco 1013 , 1024 , 1036 , 1044 , 1050 a 1062 používejte pouze ASCII interpretace číslice , znak slova a hranice slova (např. 1072 bohužel vrací 1081 ). Viz můj příspěvek na JavaScript, Regex a Unicode pro další detaily. Přidání podpory Unicode do těchto tokenů by způsobilo neočekávané chování pro tisíce webů, ale mohlo by být bezpečně implementováno pomocí nového 1092 vlajka (inspirovaná Pythonovým 1107 nebo 1118 příznak) a odpovídající 1120 vlastnictví. Protože je ve skutečnosti docela běžné ne chcete, aby tyto tokeny měly povoleno Unicode v konkrétních vzorech regulárních výrazů, nový příznak, který aktivuje podporu Unicode, by nabídl to nejlepší z obou světů.

Změnit chování resetování zpětné reference během opakování dílčího vzoru

Skutečný návrh:Nikdy neresetujte zpětné referenční hodnoty během zápasu

Stejně jako poslední problém se zpětnou referencí, i toto řešil David Andersson ve svém příspěvku ECMAScript 3 Regular Expressions:Specifikace, která nedává smysl . Problém se zde týká hodnoty, kterou si pamatuje zachycení skupin vnořených do kvantifikované vnější skupiny (např. 1135 ). Podle tradičního chování je hodnota, kterou si zachycující skupina v rámci kvantifikovaného seskupení zapamatuje, jakákoliv, s jakou se skupina shodovala při poslední účasti v zápase. Takže hodnota 1148 po 1158 se používá pro shodu s 1161 bude 1172 . Podle ES3/ES5 je však hodnota zpětných referencí na vnořená seskupení resetována/vymazána po zopakování vnějšího seskupení. Proto 1182 bude stále odpovídat 1190 , ale po dokončení shody 1205 by odkazovalo na nezúčastněnou zachytávací skupinu, která by v JavaScriptu odpovídala prázdnému řetězci v samotném regulárním výrazu a byla by vrácena jako 1218 např. v poli vráceném 1227 .

Můj případ pro změnu spočívá v tom, že současné chování JavaScriptu se vymyká standardu v jiných variantách regulárních výrazů a nehodí se k různým typům kreativních vzorců (viz jeden příklad v mém příspěvku na téma Zachycení více, volitelné hodnoty atributu HTML ), a podle mého názoru je mnohem méně intuitivní než běžnější alternativní chování regulárních výrazů.

Věřím, že toto chování je bezpečné změnit ze dvou důvodů. Za prvé, toto je obecně problém okrajového případu pro všechny, kromě hardcore mágů s regulárními výrazy, a byl bych překvapen, kdybych našel regulární výrazy, které se spoléhají na verzi tohoto chování v JavaScriptu. Za druhé, a co je důležitější, Internet Explorer toto pravidlo neimplementuje a řídí se tradičnějším chováním.

Přidat příznak /s již

Skutečný návrh:Přidejte příznak /s (a odpovídající vlastnost RegExp.prototype.dotall), která změní tečku tak, aby odpovídala všem znakům včetně nových řádků

Tuto funkci vložím spíše jako změnu/opravu než jako novou funkci, protože použití 1234 není zrovna obtížné místo tečky, když chcete chování 1240 . Předpokládám 1251 flag byl doposud vyloučen, aby se zachránili nováčci před nimi samými a omezily se škody způsobené únikovým backtrackingem, ale nakonec se stane to, že lidé píší strašně neefektivní vzory jako 1265 místo toho.

Vyhledávání podle regulárních výrazů v JavaScriptu je jen zřídka založené na řádcích, a proto je běžnější chtít, aby tečka zahrnovala nové řádky, než aby odpovídala čemukoli jinému než nové řádky (ačkoli oba režimy jsou užitečné). Je rozumné ponechat výchozí význam tečky (žádné nové řádky), protože ji sdílejí jiné varianty regulárních výrazů a je vyžadována pro zpětnou kompatibilitu, ale přidáním podpory pro 1270 vlajka je po splatnosti. Logická hodnota označující, zda byl tento příznak nastaven, by se měla zobrazit v regulárních výrazech jako vlastnost s názvem buď 1281 (nešťastné jméno z Perlu, .NET atd.) nebo popisnější 1294 (používá se v Javě, Pythonu, PCRE atd.).

Osobní preference

Následuje několik změn, které by vyhovovaly mým preferencím, i když si nemyslím, že by je většina lidí považovala za významné problémy:

  • Povolit literály regulárních výrazů používat lomítka bez speciálních znaků v rámci tříd znaků (např. 1303 ). To již bylo zahrnuto v opuštěných návrzích změn ES4.
  • Povolit 1310 bez kódování znaků jako první znak ve třídách znaků (např. 1322 nebo 1337 ). To je povoleno pravděpodobně v každé jiné variantě regulárního výrazu, ale vytvoří prázdnou třídu následovanou doslovným 1347 v JavaScriptu. Rád bych si představil, že nikdo nepoužívá prázdné třídy záměrně, protože nefungují konzistentně napříč prohlížeči a existují široce používané alternativy se zdravým rozumem (1352 místo 1364 a 1376 místo 1382 ). Bohužel, dodržování této zvláštnosti JavaScriptu je testováno v Acid3 (test 89), což je pravděpodobně dost na to, aby zabilo požadavky na tuto zpětně nekompatibilní, ale rozumnou změnu.
  • Změňte 1396 token používaný v náhradních řetězcích na 1402 . Prostě to dává smysl. (Ekvivalenty v jiných variantách nahrazujícího textu pro srovnání:Perl:1416; Java:1420; .NET:1435 , 1440; PHP:1452 , 1461; Ruby:1474 , 1481; Python:1495 .)
  • Zbavte se zvláštního významu 1502 . V rámci znakových tříd je to metasekvence 1514 odpovídá znaku backspace (ekvivalent 1526 ). To je zbytečné pohodlí, protože nikoho nezajímá shoda znaků backspace a je to matoucí vzhledem k tomu, že 1535 odpovídá hranici slova při použití mimo třídy znaků. I když by to narušilo tradici regulárního výrazu (kterou bych obvykle obhajoval, myslím si, že 1547 by neměl mít žádný zvláštní význam uvnitř tříd znaků a jednoduše odpovídat doslovnému 1550 .

Opraveno v ES3:Odstraňte odkazy na osmičkové znaky

ECMAScript 3 odstranil odkazy na osmičkové znaky ze syntaxe regulárního výrazu, ačkoli 1563 byl zachován jako výhodná výjimka, která umožňuje snadné porovnání znaku NUL. Prohlížeče si však obecně udržují plnou osmičkovou podporu kvůli zpětné kompatibilitě. Osmičkové soustavy jsou v regulárních výrazech velmi matoucí, protože jejich syntaxe se překrývá se zpětnými odkazy a mimo třídy znaků je povolena další úvodní nula. Zvažte následující regulární výrazy:

  • 1575 :1585 je osmičkový.
  • 1597 :1601 je zpětná reference.
  • 1610 :1626 je osmičkový.
  • 1636 :1643 je zpětná reference; 1654 je osmičkový.
  • 1667 :Všechny výskyty 1679 a 1687 jsou osmičkové. Podle specifikací ES3+ však čísla za každým 1693 by mělo být zacházeno (s výjimkou nestandardních rozšíření) jako doslovné znaky, které zcela mění to, čemu tento regulární výraz odpovídá. (Edit-2012:Ve skutečnosti podrobné přečtení specifikace ukazuje, že jakákoli 0-9 následující za 1702 by měl způsobit 1712 .)
  • 1722 :1733 mimo třídu znaků je osmička; ale uvnitř osmička končí třetí nulou (tj. třída znaků odpovídá indexu znaku nula nebo 1740 ). Tento regulární výraz je tedy ekvivalentní 1751; ačkoli, jak bylo zmíněno výše, dodržování ES3 by změnilo význam.
  • 1763 :Mimo třídu znaků osmičkové číslo končí čtvrtou nulou a následuje doslovný 1776 . Uvnitř osmička končí na třetí nule a následuje doslovný 1781 . A ještě jednou, ES3 vyloučení oktalů a zahrnutí 1791 mohl změnit význam.
  • 1804 :Vzhledem k tomu, že v JavaScriptu zpětné odkazy na zachycující skupiny, které se (zatím) neúčastnily, odpovídají prázdnému řetězci, odpovídá tento regulární výraz 1812 (tj. 1823 se považuje za zpětnou referenci, protože se v regulárním výrazu objevuje odpovídající skupina zachycení) nebo odpovídá 1831 (tj. 1846 se považuje za osmičkovou, protože se objevuje před jeho odpovídající skupina)? Není překvapením, že prohlížeče nesouhlasí.
  • 1851 :Teď jsou věci opravdu chlupaté. Odpovídá tento regulární výraz 1867? , 1877 , 1883 , 1891 , 1905 nebo 1913 ? Všechny tyto možnosti se zdají věrohodné a prohlížeče se na správné volbě neshodnou.

Existují také další problémy, kterých je třeba se obávat, například zda osmičkové znaky jdou až do 1922 (1934 , 8bitové) nebo 1946 (1953 , 9-bit); ale v každém případě jsou osmičky v regulárních výrazech matoucí cluster-cuss. Přestože ECMAScript již tento nepořádek vyčistil odstraněním podpory pro osmičkové číslice, prohlížeče jej nenásledovaly. Kéž by to udělali, protože na rozdíl od výrobců prohlížečů se o tento kousek dědictví nemusím starat (nikdy nepoužívám osmičkové soustavy v regulárních výrazech a ani vy byste neměli).

Opraveno v ES5:Neukládat do mezipaměti literály regulárních výrazů

Podle pravidel ES3 nevytvářely literály regulárních výrazů nový objekt regulárních výrazů, pokud byl literál se stejnou kombinací vzor/příznak již použit ve stejném skriptu nebo funkci (toto se nevztahuje na regulární výrazy vytvořené kódem 1963 konstruktér). Častým vedlejším efektem bylo, že literály regulárních výrazů používají 1970 vlajka neměla svůj 1980 vlastnost reset v některých případech, kdy by to většina vývojářů očekávala. Několik prohlížečů nedodrželo specifikaci tohoto neintuitivního chování, ale Firefox ano, a v důsledku toho se stal druhým nejvíce duplicitním hlášením o chybě JavaScriptu pro Mozillu. Naštěstí se ES5 tohoto pravidla zbavilo a nyní je nutné literály regulárních výrazů překompilovat pokaždé, když na ně narazíte (tato změna přichází ve Firefoxu 3.7).

———
Tak tady to máte. Nastínil jsem, co si myslím, že JavaScript RegExp API udělalo chybu. Souhlasíte se všemi těmito návrhy, nebo bych vy, kdybyste se nemuseli starat o zpětnou kompatibilitu? Existují lepší způsoby než ty, které jsem navrhoval, jak vyřešit problémy zde diskutované? Máte nějaké další výhrady k existujícím funkcím regulárního výrazu JavaScriptu? Těším se na zpětnou vazbu.

Protože jsem se v tomto příspěvku zaměřil na negativa, poznamenám, že práci s regulárními výrazy v JavaScriptu považuji za obecně příjemnou zkušenost. JavaScriptu je toho zatraceně hodně.