正则表达式可以被用于 RegExp 的 exec 和 test 方法以及 String 的 match、replace、search 和 split 方法。
本文主要介绍 RegExp 的相关属性和方法。
RegExp[@@species] 访问器属性返回RegExp 的构造器。
RegExp[Symbol.species]
在派生的正则类(也就是你自定义的正则类 MyRegExp)中,MyRegExp 的 species 是 MyRegExp 构造器。但是,你可能希望覆盖它,以便在你的派生类方法中,返回 RegExp 父类对象:
class MyRegExp extends RegExp {
// 将 MyRegExp species 覆盖为 RegExp 父类构造器
static get [Symbol.species]() {
return RegExp;
}
}
lastIndex 是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。
lastIndex = regExpObj.lastIndex;
只有正则表达式使用了表示全局检索的 “g” 或者粘性检索的 “y” 标志时,该属性才会起作用。此时应用下面的规则:
考虑下面的语句:
var re = /(hi)?/g;
匹配空字符串
console.log(re.exec("hi"));
console.log(re.lastIndex);
返回 [“hi”, “hi”] ,lastIndex 等于 2。
console.log(re.exec("hi"));
console.log(re.lastIndex);
返回 [“”, undefined],即一个数组,其第 0 个元素为匹配的字符串。此种情况下为空字符串,是因为 lastIndex 为 2(且一直是 2),“hi” 长度为 2。
dotAll 属性表明是否在正则表达式中一起使用"s"修饰符(引入/s 修饰符,使得。可以匹配任意单个字符)。dotAll 是一个只读的属性,属于单个正则表达式实例。
如果使用了"s"修饰符,dotAll 的值将返回Boolean类型的true,否则将返回false。“s"修饰符表示,特殊字符”."应另外匹配字符串中的下述行终结符(line terminator characters),否则将会失配:
无法直接修改此属性。
flags属性返回一个字符串,由当前正则表达式对象的标志组成。
flags属性中的标志以字典序排序(从左到右,即"gimuy")。
/foo/gi.flags; // "gi"
/bar/muy.flags; // "muy"
if (RegExp.prototype.flags === undefined) {
Object.defineProperty(RegExp.prototype, "flags", {
configurable: true,
get: function () {
return this.toString().match(/[gimuy]*$/)[0];
}
});
}
global 属性表明正则表达式是否使用了 “g” 标志。global 是一个正则表达式实例的只读属性。
global 的值是布尔对象,如果使用了 “g” 标志,则返回 true;否则返回 false。 “g” 标志意味着正则表达式应该测试字符串中所有可能的匹配。
你无法直接更改此属性。
var regex = new RegExp("foo", "g");
console.log(regex.global); // true
hasindexes访问器属性指示是否将d标志与正则表达式一起使用。
如果使用了d标志,则regexp.prototype.hasindexes的值为true;否则,false。d标志表示正则表达式匹配的结果应该包含每个捕获组的子字符串的开始和结束索引。它不会以任何方式改变正则表达式的解释或匹配行为,而只是在匹配结果中提供额外的信息。hasindexes的set访问器未定义。您不能直接更改此属性。
const str1 = "foo bar foo";
const regex1 = /foo/dg;
console.log(regex1.hasIndices); // Output: true
console.log(regex1.exec(str1).indices[0]); // Output: Array [0, 3]
console.log(regex1.exec(str1).indices[0]); // Output: Array [8, 11]
const str2 = "foo bar foo";
const regex2 = /foo/;
console.log(regex2.hasIndices); // Output: false
console.log(regex2.exec(str2).indices); // Output: undefined
ignoreCase 属性表明正则表达式是否使用了 “i” 标志。ignoreCase 是正则表达式实例的只读属性。
ignoreCase 的值是布尔对象,如果使用了"i" 标志,则返回 true;否则,返回 false。“i” 标志意味着在字符串进行匹配时,应该忽略大小写。
你无法直接更改此属性。
var regex = new RegExp("foo", "i");
console.log(regex.ignoreCase); // true
multiline 属性表明正则表达式是否使用了 “m” 标志。multiline 是正则表达式实例的一个只读属性。
multiline 是一个布尔对象,如果使用了 “m” 标志,则返回 true;否则,返回 false。“m” 标志意味着一个多行输入字符串被看作多行。例如,使用 “m”,“^” 和 “$” 将会从只匹配正则字符串的开头或结尾,变为匹配字符串中任一行的开头或结尾。
你无法直接更改此属性。
var regex = new RegExp("foo", "m");
console.log(regex.multiline); // true
source 属性返回一个值为当前正则表达式对象的模式文本的字符串,该字符串不会包含正则字面量两边的斜杠以及任何的标志字符。
var regex = /fooBar/gi;
console.log(regex.source); // "fooBar",不包含 /.../ 和 "ig"。
sticky 属性反映了搜索是否具有粘性( 仅从正则表达式的 lastIndex 属性表示的索引处搜索 )。sticky 是正则表达式对象的只读属性。
sticky 的值是 Boolean ,并在 y 标志使用时为真; 否则为假。y 标志指示,仅从正则表达式的 lastIndex 属性表示的索引处为目标字符串匹配(并且不会尝试从后续索引匹配)。如果一个表达式同时指定了 sticky 和 global,其将会忽略 global 标志。
你不能直接更改这个属性,它是只读的。
var str = "#foo#";
var regex = /foo/y;
regex.lastIndex = 1;
regex.test(str); // true(译注:此例仅当 lastIndex = 1 时匹配成功,这就是 sticky 的作用)
regex.lastIndex = 5;
regex.test(str); // false(lastIndex 被 sticky 标志考虑到,从而导致匹配失败)
regex.lastIndex; // 0(匹配失败后重置)
unicode 属性表明正则表达式带有"u" 标志。 unicode 是正则表达式独立实例的只读属性。
unicode 的值是 Boolean,并且如果使用了 “u” 标志则为 true;否则为 false。“u” 标志开启了多种 Unicode 相关的特性。使用 “u” 标志,任何 Unicode 代码点的转义都会被解释。
你不能直接修改这个属性,它是只读的。
var regex = new RegExp("\u{61}", "u");
console.log(regex.unicode); // true
exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。
exec(str)
如果匹配失败,exec() 方法返回 null,并将正则表达式的 lastIndex 重置为 0 。
如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的 lastIndex 属性。完全匹配成功的文本将作为返回数组的第一项,从第二项起,后续每项都对应一个匹配的捕获组。数组还具有以下额外的属性:
index
匹配到的字符位于原始字符串的基于 0 的索引值。
input
匹配的原始字符串。
groups
一个命名捕获组对象,其键是名称,值是捕获组。若没有定义命名捕获组,则 groups 的值为 undefined。
indices 可选
此属性仅在设置了 d 标志位时存在。它是一个数组,其中每一个元素表示一个子字符串的边界。每个子字符串匹配本身就是一个数组,其中第一个元素表示起始索引,第二个元素表示结束索引。
在设置了 global 或 sticky 标志位的情况下(如 /foo/g 或 /foo/y),JavaScript RegExp 对象是有状态的。它们会将上次成功匹配后的位置记录在 lastIndex 属性中。使用此特性,exec() 可用来对单个字符串中的多次匹配结果进行逐条的遍历(包括捕获到的匹配),而相比之下, String.prototype.match() 只会返回匹配到的结果。
在使用 exec() 时,global 标志位不会在 sticky 标志位被设置时生效,而 match() 始终会设置 sticky 标志位。
exec() 是正则表达式的原始方法。许多其它的正则表达式方法会在内部调用 exec()——包括一些字符串方法也会调用 exec(),如 @@replace。虽然 exec() 本身非常强大而又有效,但它通常不能最清楚地表示调用的目的。
// Match "quick brown" followed by "jumps", ignoring characters in between
// Remember "brown" and "jumps"
// Ignore case
const re = /quick\s(?brown).+?(jumps) /dgi;
const result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog");
test() 方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 true 或 false。
regexObj.test(str)
如果正则表达式与指定的字符串匹配 ,返回true;否则false。
let str = "hello world!";
let result = /^hello/.test(str);
console.log(result);
// true
toString() 返回一个表示该正则表达式的字符串。
regexObj.toString()
RegExp 对象覆盖了 Object 对象的 toString() 方法,并没有继承 Object.prototype.toString()。对于 RegExp 对象,toString 方法返回一个该正则表达式的字符串形式。
myExp = new RegExp("a+b+c");
alert(myExp.toString()); // 显示 "/a+b+c/"
foo = new RegExp("bar", "g");
alert(foo.toString()); // 显示 "/bar/g"
对正则表达式匹配字符串时,**@@match**方法用于获取匹配结果。
regexp[Symbol.match](str)
match 方法会返回一个数组,它包括整个匹配结果,和通过捕获组匹配到的结果,如果没有匹配到则返回 null
这个方法在 String.prototype.match() 的内部调用。例如,下面的两个方法返回相同结果。
"abc".match(/a/);
/a/[Symbol.match]("abc");
这个方法为自定义 RegExp 子类中的匹配行为而存在。
这个方法的使用方式和 String.prototype.match() 相同,不同之处是 this 和参数顺序。
var re = /[0-9]+/g;
var str = "2016-01-02";
var result = re[Symbol.match](str);
console.log(result); // ["2016", "01", "02"]
在子类中使用@@match
RegExp 的子类可以覆写 @@match方法来修改默认行为。
class MyRegExp extends RegExp {
[Symbol.match](str) {
var result = RegExp.prototype[Symbol.match].call(this, str);
if (!result) return null;
return {
group(n) {
return result[n];
}
};
}
}
var re = new MyRegExp("([0-9]+)-([0-9]+)-([0-9]+)");
var str = "2016-01-02";
var result = str.match(re); // String.prototype.match calls re[@@match].
console.log(result.group(1)); // 2016
console.log(result.group(2)); // 01
console.log(result.group(3)); // 02
**[@@matchAll]**方法返回对字符串使用正则表达式的所有匹配项。
regexp[Symbol.matchAll](str)
一个迭代器。
本方法在String.prototype.matchAll()中被内部调用。例如,以下两个示例返回相同的结果。
"abc".matchAll(/a/);
/a/[Symbol.matchAll]("abc");
本方法用于自定义RegExp子类中的匹配行为。
直接调用
本方法的使用方法几乎与String.prototype.matchAll()相同,除了this 的不同以及参数顺序的的差异。
var re = /[0-9]+/g;
var str = "2016-01-02";
var result = re[Symbol.matchAll](str);
console.log(Array.from(result, x => x[0]));
// ["2016", "01", "02"]
在子类中使用@@matchAll
RegExp的子类可以重写@@matchAll方法来修改默认行为。例如,返回一个Array而不是iterator:
class MyRegExp extends RegExp {
[Symbol.matchAll](str) {
var result = RegExp.prototype[Symbol.matchAll].call(this, str);
if (!result) {
return null;
} else {
return Array.from(result);
}
}
}
var re = new MyRegExp("([0-9]+)-([0-9]+)-([0-9]+)", "g");
var str = "2016-01-02|2019-03-07";
var result = str.matchAll(re);
console.log(result[0]); // [ "2016-01-02", "2016", "01", "02" ]
console.log(result[1]); // [ "2019-03-07", "2019", "03", "07" ]
@@replace 方法会在一个字符串中用给定的替换器,替换所有符合正则模式的匹配项,并返回替换后的新字符串结果。用来替换的参数可以是一个字符串或是一个针对每次匹配的回调函数。
regexp[Symbol.replace](str, newSubStr|function)
str
正则替换的目标字符串。
newSubStr (replacement)
类型为 String 的替换器。支持大多数特殊的替换匹配模式;
function (replacement)
生成新的子字符串的回调函数替换器。
用替换器替换相应匹配项后的新字符串。
如果匹配模式也是RegExp对象,这个方法在 String.prototype.replace() 的内部调用。例如,下面的两个方法返回相同结果。
"abc".replace(/a/, "A");
/a/[Symbol.replace]("abc", "A");
该方法是为了在 RegExp 子类中自定义匹配的替换模式。
如果匹配模式不是一个RegExp 对象,String.prototype.replace() 就不会调用该方法,也不会创建一个 RegExp对象。
直接调用
这个方法基本可以和 String.prototype.replace() 一样使用,不同之处是 this 和参数顺序。
var re = /-/g;
var str = "2016-01-01";
var newstr = re[Symbol.replace](str, ".");
console.log(newstr); // 2016.01.01
在子类中使用 @@replace
RegExp 的子类可以覆写 @@replace方法来修改默认行为。
class MyRegExp extends RegExp {
constructor(pattern, flags, count) {
super(pattern, flags);
this.count = count;
}
[Symbol.replace](str, replacement) {
// Perform @@replace |count| times.
var result = str;
for (var i = 0; i < this.count; i++) {
result = RegExp.prototype[Symbol.replace].call(this, result, replacement);
}
return result;
}
}
var re = new MyRegExp("\\d", "", 3);
var str = "01234567";
var newstr = str.replace(re, "#"); // String.prototype.replace calls re[@@replace].
console.log(newstr); // ###34567
@@search 方法执行了一个在给定字符串中的一个搜索以取得匹配正则模式的项。
regexp[Symbol.search](str)
整数
如果成功的话,@@search 返回该正则模式的第一个匹配项的在字符串中的位置索引。否则将返回-1。
这个方法在 String.prototype.search() 的内部调用。例如,下面的两个方法返回相同结果。
"abc".search(/a/);
/a/[Symbol.search]("abc");
这个方法为自定义 RegExp 子类中的匹配行为而存在。
直接调用
这个方法的使用方式和 String.prototype.search() 相同,不同之处是 this 和参数顺序。
var re = /-/g;
var str = "2016-01-02";
var result = re[Symbol.search](str);
console.log(result); // 4
在子类中使用@@search
{jsxref(“RegExp”)}} 的子类可以覆写 @@search方法来修改默认行为。
class MyRegExp extends RegExp {
constructor(str) {
super(str);
this.pattern = str;
}
[Symbol.search](str) {
return str.indexOf(this.pattern);
}
}
var re = new MyRegExp("a+b");
var str = "ab a+b";
var result = str.search(re); // String.prototype.search calls re[@@search].
console.log(result); // 3
@@split 方法切割 String 对象为一个其子字符串的数组 。
regexp[Symbol.split](str[, limit])
str
切割操作的目标字符串
limit
可选。一个为了限制切割数量的特定整数。 @@split 防范仍会切割每个匹配正则模式的匹配项,直到切割数量达到该限制数,除非提前切割完字符串。
包含其子字符串的Array 。
如果切割器是一个RegExp对象,这个方法就将在 String.prototype.split() 的内部调用。例如,下面的两个方法返回相同结果。
"a-b-c".split(/-/);
/-/[Symbol.split]("a-b-c");
这个方法为自定义 RegExp 子类中的匹配行为而存在。
如果 str 参数不是一个RegExp 对象,String.prototype.split() 就不会调用该方法,也不会创建一个 RegExp 对象。
直接调用
这个方法的使用方式和 String.prototype.split() 相同,不同之处是 this 和参数顺序。
var re = /-/g;
var str = "2016-01-02";
var result = re[Symbol.split](str);
console.log(result); // ["2016", "01", "02"]
在子类中使用 @@split
RegExp 的子类可以覆写 @@split方法来修改默认行为。
class MyRegExp extends RegExp {
[Symbol.split](str, limit) {
var result = RegExp.prototype[Symbol.split].call(this, str, limit);
return result.map(x => "(" + x + ")");
}
}
var re = new MyRegExp("-");
var str = "2016-01-02";
var result = str.split(re); // String.prototype.split calls re[@@split].
console.log(result); // ["(2016)", "(01)", "(02)"]
如果你感觉文章不咋地
//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果你觉得该文章有一点点用处,可以给作者点个赞;\\*^o^*//
如果你想要和作者一起进步,可以微信扫描二维码,关注前端老L;~~~///(^v^)\\\~~~
谢谢各位读者们啦(^_^)∠※!!!