Firefox obsahuje nestandardní rozšíření JavaScriptu, které umožňuje volat regulární výrazy jako funkce. Toto slouží jako zkratka pro volání exec
regulárního výrazu metoda. Například ve Firefoxu /regex/("string")
je ekvivalentní /regex/.exec("string")
. Dřívější návrhy ECMAScript 4 naznačovaly, že tato funkce bude přidána do specifikace ES4, ale následná diskuse na konferenci ES4-discuss naznačuje, že by mohla být zrušena.
Něco podobného však můžete implementovat přidáním call
a apply
metody na RegExp.prototype
, což by mohlo pomoci s funkčním programováním a kódem typu duck, který pracuje jak s funkcemi, tak s regulárními výrazy. Pojďme je tedy přidat:
RegExp.prototype.call = function (context, str) { return this.exec(str); }; RegExp.prototype.apply = function (context, args) { return this.exec(args[0]); };
Všimněte si, že obě výše uvedené metody zcela ignorují context
argument. Můžete předat null
nebo cokoli jiného jako kontext a dostanete zpět normální výsledek spuštění exec
na regulárním výrazu. Pomocí výše uvedených metod můžete obecně pracovat s regulárními výrazy i funkcemi, kdekoli je to vhodné. Několik zjevných případů, kdy by to mohlo být užitečné, jsou metody iterace pole JavaScriptu 1.6. Následují implementace filter
, every
, some
a map
které umožňují jejich použití v různých prohlížečích:
// Returns an array with the elements of an existng array for which the provided filtering function returns true Array.prototype.filter = function (func, context) { var results = []; for (var i = 0; i < this.length; i++) { if (i in this && func.call(context, this[i], i, this)) results.push(this[i]); } return results; }; // Returns true if every element in the array satisfies the provided testing function Array.prototype.every = function (func, context) { for (var i = 0; i < this.length; i++) { if (i in this && !func.call(context, this[i], i, this)) return false; } return true; }; // Returns true if at least one element in the array satisfies the provided testing function Array.prototype.some = function (func, context) { for (var i = 0; i < this.length; i++) { if (i in this && func.call(context, this[i], i, this)) return true; } return false; }; // Returns an array with the results of calling the provided function on every element in the provided array Array.prototype.map = function (func, context) { var results = []; for (var i = 0; i < this.length; i++) { if (i in this) results[i] = func.call(context, this[i], i, this); } return results; };
Protože pole a null
hodnoty vrácené exec
type-convert pěkně na true
a false
, výše uvedený kód vám umožňuje použít něco jako ["a","b","ab","ba"].filter(/^a/)
vrátit všechny hodnoty, které začínají "a":["a","ab"]
. Kód ["1",1,0,"a",3.1,256].filter(/^[1-9]\d*$/)
vrátí celá čísla větší než nula, bez ohledu na typ:["1",1,256]
. str.match(/a?b/g).filter(/^b/)
vrátí všechny shody písmene „b“, které nepředchází „a“. To může být pohodlný vzor, protože JavaScript nepodporuje lookbehind.
Všechny výše uvedené příklady již fungují s nativním Array.prototype.filter
Firefoxu kvůli nepřímému exec
funkce volání v tomto prohlížeči, ale nefungovaly by s implementací filter
napříč prohlížeči výše bez přidání RegExp.prototype.call
.
Zdá se vám to jako něco, co by vám bylo užitečné? Napadají vás další dobré příklady, kde je call
a apply
byly by metody užitečné pro regulární výrazy?
Aktualizace: Tento příspěvek byl přeložen do čínštiny pomocí PlanABC.net.