JS对象类型-RegExp

本篇文章主要介绍RegExp对象以及RegExp的实例的属性和方法,如果对于正则的基础语法还不是很清楚,可以参考下RegExp基础语法这篇文章

实例属性

RegExp实例都包含下面5个属性

global: 布尔值,表示是否设置了g标志
ignoreCase: 布尔值,表示是否设置了i标志
multiline:布尔值,表示是否设置了m标志
lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0开始
source:正则表达式的字符串表示(按照字面量形式而非传入构造函数中的字符串模式返回)
var p1 = /[bc]at/i;

console.log(p1.global);//false
console.log(p1.ignoreCase);//true    
console.log(p1.multiline);//false
console.log(p1.lastIndex);//0
console.log(p1.source);//'[bc]at'

如果设置了RegExp的全局模式'g',使用exec()或test()函数时,正则表达式的匹配就会从lastIndex的位置开始,并且在每次匹配成功之后重新设定lastIndex。这样,就可以在字符串中重复迭代,依次寻找各个匹配结果。但是,如果需要对不同字符串调用同一个RegExp的exec()或test()方法,这个变量可能会带来意料之外的匹配结果,所以在更换字符串时,要显式地将RegExp的lastIndex置为0

var p1 = /\w/g;
var s1 = 'ab';
var s2 = 'ba';

// 默认值
console.log(p1.lastIndex); // 0

p1.exec(s1);
console.log(p1.lastIndex); // 1
// s2从位置1开始匹配
p1.exec(s2);
console.log(p1.lastIndex); // 2

构造函数属性

RegExp构造函数属性会基于所执行的最近一次正则表达式操作而变化。有两种方式访问它们,即长属性名和短属性名,短属性名大都不是有效的ECMAScript标识符,所以必须通过方括号语法来访问它们

长属性名           短属性名         说明
input             $_                最近一次要匹配的字符串
lastMatch         $&                最近一次的匹配项
lastParen         $+                最近一次匹配的捕获组
leftContext       $`                input字符串中lastMatch之前的文本
rightContext      $'                input字符串中lastMatch之后的文本
multiline         $*                布尔值,表示是否所有表达式都使用多行模式
var text = 'this has been a short summer';
var pattern = /(.)hort/g;
if(pattern.test(text)){
    console.log(RegExp.input);//'this has been a short summer'
    console.log(RegExp.leftContext);//'this has been a '
    console.log(RegExp.rightContext);//' summer'
    console.log(RegExp.lastMatch);//'short'
    console.log(RegExp.lastParen);//'s'
    console.log(RegExp.multiline);//false

    console.log(RegExp['$_']);//'this has been a short summer'
    console.log(RegExp['$`']);//'this has been a '
    console.log(RegExp["$'"]);//' summer'
    console.log(RegExp['$&']);//'short'
    console.log(RegExp['$+']);//'s'
    console.log(RegExp['$*']);//false        
}

JavaScript有9个用于存储捕获组的构造函数属性,RegExp.$1、RegExp.$2、RegExp.$3……到RegExp.$9分别用于存储第一、第二……第九个匹配的捕获组。在调用exec()或test()方法时,这些属性会被自动填充

比如,要匹配诸如2018-08-12这样的日期字符串

/(\d{4})-(\d{2})-(\d{2})/.test('2018-08-12');
console.log(RegExp.$1);//'2018'
console.log(RegExp.$2);//'08'
console.log(RegExp.$3);//'12'
console.log(RegExp.$4);//''

// 理论上,应该保存整个表达式匹配文本的RegExp.$0并不存在,值为undefined
console.log(RegExp.$0);//undefined

实例方法

实例方法分为两类:一类是是继承而来的,包括toString()、toLocalString()、valueOf();一类是非继承的,包括test()和exec()

继承方法

RegExp对象继承了Object对象的通用方法toString()、toLocaleString()、valueOf()这三个方法

toString():toString()方法返回正则表达式的字面量

toLocaleString():toLocaleString()方法返回正则表达式的字面量

valueOf():valueOf()方法返回返回正则表达式对象本身

var pattern = new RegExp('[bc]at','gi');
console.log(pattern.toString()); // '/[bc]at/gi'
console.log(pattern.toLocaleString()); // '/[bc]at/gi'
console.log(pattern.valueOf()); // /[bc]at/gi

var pattern = /[bc]at/gi;
console.log(pattern.toString()); // '/[bc]at/gi'
console.log(pattern.toLocaleString()); // '[bc]at/gi'
console.log(pattern.valueOf()); // /[bc]at/gi

注意: 不论以哪种方式创建正则表达式,这三个方法都只返回其字面量形式

exec()

exec()方法专门为捕获组而设计,接受一个参数,表示要应用模式的字符串,返回包含匹配项信息的数组,在没有匹配项的情况下返回null

匹配项数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含第一项)

返回的数组包含两个额外的属性:index和input。index表示匹配项在字符串的位置,input表示应用正则表达式的字符串

console.log(/(\d{4})-(\d{2})-(\d{2})/.exec('date 2018-08-12 10:30'));

对于exec()方法,在不设置全局标志的情况下,在同一个字符串上多次调用exec(),将始终返回第一个匹配项的信息;而在设置全局标志的情况下,每次调用exec()都会在字符串中继续查找新匹配项。

无全局标志示例

var text = 'cat,bat,sat,fat';
var pattern = /.at/;
var m1 = pattern.exec(text);
console.log(m1);    
var m2 = pattern.exec(text);
console.log(m2);

有全局标志示例

var text = 'cat,bat,sat,fat';
var pattern = /.at/g;
var m1 = pattern.exec(text);
console.log(m1);    
var m2 = pattern.exec(text);
console.log(m2);

扩展: 用exec()方法找出所有匹配项的位置和值

var str = 'a1b2c3d4';
var p = /[a-z]/g;
var i = [], v = [], ret;
while((ret = p.exec(str)) != null) {
  i.push(ret.index);
  v.push(ret[0]);
}
console.log(i, v); // [0, 2, 4, 6] ["a", "b", "c", "d"]

test()

test()方法用来测试正则表达式能否在字符串中找到匹配文本,接收一个字符串参数,匹配时返回true,否则返回false

/\d/.test('1'); // true
/\d/.test('a'); // false

同样地,在调用test()方法时,会造成RegExp对象的lastIndex属性的变化。如果指定了全局模式,每次执行test()方法时,都会从字符串中的lastIndex偏移值开始尝试匹配,所以用同一个RegExp多次验证不同字符串,必须在每次调用之后,将lastIndex值置为0

var pattern = /^\d{4}-\d{2}-\d{2}$/g;
console.log(pattern.test('2018-08-12'));//true
console.log(pattern.test('2018-08-12'));//false

//正确的做法应该是在验证不同字符串前,先将lastIndex重置为0
var pattern = /^\d{4}-\d{2}-\d{2}$/g;
console.log(pattern.test('2018-08-12'));//true
pattern.lastIndex = 0;
console.log(pattern.test('2018-08-12'));//true
posted @ 2021-09-29 14:23  wmui  阅读(107)  评论(0编辑  收藏  举报