在 ES5 中,RegExp构造函数的参数有两种情况。
第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。
第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。
但是,ES5 不允许此时使用第二个参数添加修饰符,否则会报错。
ES6 改变了这种行为。如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符。

正则表达式的拓展

在es5中的正则写法

1
2
3
4
5
6
7
{
// 两个字符串方式,i 代表忽略大小写
let reg1 = new RegExp('xyz', 'i');
// 一般形式,正则表达式的形式
let reg2 = new RegExp(/xyz/i);
console.log(reg1.test('xYz123'), reg2.test('xyZ123')); // true, true
}

es6 中的写法

1
2
3
4
5
6
7
8
{
// 构造函数的变化。
// 第一个参数允许是正则的形式。
// 第二个参数允许是正则的修饰符。
let reg = new RegExp(/xyz/ig, 'i');
// flags 属性是输出当前表达式的 修饰符。
console.log(reg.flags); // i
}

新增的 修饰符 y u

y 修饰符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
let string = 'bbb_b_b';
let reg1 = /b+/g;
let reg2 = /b+/y;
// 第一次匹配
console.log('one', reg1.exec(string), reg2.exec(string));
// bbb; bbb
// 第二次匹配
console.log('two', reg1.exec(string), reg2.exec(string));
// bb; null
// 相同:都是全局匹配的修饰符。
// 区别: g 修饰符匹配下一个字符串不一定是紧跟着的字符开始。
// 区别:y 修饰符下一次匹配必须是紧跟着的字符。
// 判断是否开启了 y 修饰符。sticky 属性
console.log(reg1.sticky, reg2.sticky); // false, true
}

u 修饰符 Unicode 字符的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
console.log('u-1', /^\uD83D/.test('\uD83D\uDC2A')); // true
console.log('u-2', /^\uD83D/u.test('\uD83D\uDC2A')); // false
// 这里 没带u的会把test里面的字符当成两个字符。
// 这里 带有u的会把test里面的字符当成一个字符。
console.log(/\u{61}/.test('a')); // false
console.log(/\u{61}/u.test('a')); // true
// {} 里面的内容是作为Unicode编码的,需要带有u才能被解析。
// 关于 . 匹配字符 的一个重新认识。
console.log(`\u{20BB9}`); // 𠮹
let str = '𠮹';
console.log('u-1', /^.$/.test(str)); // false
console.log('u-2', /^.$/u.test(str)); // true
console.log('u-3', /𠮹{2}/.test('𠮹𠮹')); // false
console.log('u-4', /𠮹{2}/u.test('𠮹𠮹')); // false
// . 匹配字符,只能匹配字符长度小于2个字节的字符,
// 大于两个字节的字符需要添加 u 修饰符 . 才能匹配大于两字节的字符。
// 修复一个错误认知,就是 . 能匹配任何字符的经验。
// 虽然在 u 修饰符下 . 能匹配大于两个字节的字符。
// 但是还有 换行符,回车符,行分割符,段分割符,是不能匹配的。
// 这里就要用到 s 修饰符。
// s 修饰符现在还没有实现。
}