Regulární výrazy jako funkce

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.