2009-08-25 9 views
9

Zasadniczo moje pytanie dotyczy tego, w jaki sposób JavaScript obsługuje literały regex.Czy/regex/Literals zawsze są obiekty RegExp?

Kontrastując z liczbą, ciągiem i wartością logiczną, gdzie literały są typami danych pierwotnych i odpowiadającymi obiektami Liczba, Łańcuch i Boolean istnieją z konwersją typu bezszwowego, są regexowymi literałami anonimowymi wystąpień obiektu RegExp lub jest to przypadek traktowania regexem dane pierwotne z konwersją typu bezszwowego na RegExp?

"Kompletny odnośnik Javascript, druga edycja, Powell i Schneider (MH)" przeczą sobie samemu - w jednym miejscu autorzy mówią, że/regex/jest automatycznie przypisywane do RegExp w razie potrzeby iw innym miejscu, które mówią, że/regex/to tylko przykład RegExp!

EDIT: Proszę podać odniesienie do wiarygodnego źródła

Odpowiedz

12

Oto co ma do powiedzenia the spec:

Wyrażenie regularne dosłowny jest elementem, który jest przekształcany wejście do obiektu RegExp gdy jest skanowany. Obiekt jest tworzony przed rozpoczęciem oceny programu lub funkcji zawierającej. Ocena literału daje odniesienie do tego obiektu; nie tworzy nowego obiektu. Dwa literały wyrażenia regularnego w programie oceniają obiekty wyrażenia regularnego, które nigdy nie porównują się ze sobą, nawet jeśli zawartość dwóch liter jest identyczna.

Nie ma prymitywny typ regex że autoboxes do obiektu w taki sam sposób jak string lub number.

Należy jednak pamiętać, że nie we wszystkich przeglądarkach stosowane jest zachowanie "wystąpienie-raz-dosłownie", w tym Safari i IE6 (i ewentualnie później), więc przenośny kod nie powinien na nim polegać. Nieudanej ECMAScript 4 projekt would have changed the behavior pasujące do tych przeglądarek:

W ES3 wyrażenie regularne dosłowny jak /a*b/mg oznacza pojedynczą RegExp unikalny obiekt, który jest po raz pierwszy dosłowne napotyka się podczas oceny utworzony. W ES4 tworzony jest nowy obiekt RegExp za każdym razem, gdy literał napotkany podczas oceny.

Ponadto, niektóre przeglądarki (Firefox <3, Safari) zgłosić typeof /regex/ jak "function", więc przenośny kod powinien unikać typeof na RegExp instancji-stick z instanceof.

+0

Nie przyklejaj się do 'instanceof' .Przykryj sprawdzaniem [[Class]] (http: // thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/) – kangax

+0

Zaktualizowany link http://perfectionkills.com/instanceof-considered-harmful-or-how- to-write-a-robust-isarray/ –

+0

@FabioBeltramini zaktualizowany link jest uszkodzony –

1

Tak, nowy RegExp ("coś", "g") jest taka sama jak /coś/g

+0

Niezupełnie, w odniesieniu do znaków specjalnych i ucieczki. Z literałem regex, aby dopasować pojedynczy backspace, robisz '/ \\ /'; z konstruktorem potrzebujesz '" \\\\ "'. – Miles

+0

Dzieje się tak, ponieważ konstruktor wymaga argumentu łańcuchowego, ale regex literały mają swoją własną składnię. Nie odpowiada to jednak na pytanie :( –

+1

@Miles: ale na końcu otrzymasz wystąpienie RegExp w obu przypadkach. Pytanie nie brzmiało "jaka różnica w składni między tymi dwoma przypadkami." – Kamarey

6

Tak, Poniższe dwa wyrażenia są równoważne:

var r1 = /ab+c/i, 
    r2 =new RegExp("ab+c", "i"); 

Obiekt konstruktor obu punktów do funkcji RegExp konstruktora:

(/ab+c/i).constructor === RegExp // true 
r2.constructor === RegExp // true 

I regexp dosłowny jest instancją RegExp:

/ab+c/i instanceof RegExp // true 

Podstawową różnicą jest to, że definiowanie wyrażeń regularnych przy użyciu funkcji konstruktora pozwala budować i skompilować wyrażenie z ciągiem. Może to być bardzo przydatne do konstruowania złożonych wyrażeń, które zostaną ponownie wykorzystane.

+0

Masz rację, ale fakt, że punkty właściwości konstruktora do RegExp tak naprawdę niczego nie udowadniają. "foo" .constructor === Łańcuch również jest prawdziwy. –