JS基础——对象——正则表达式

Posted 朗妹儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS基础——对象——正则表达式相关的知识,希望对你有一定的参考价值。

  • 6-6-7 模式修正符

  • 6-6-8 优先级

  • 6-6-9 局限性

  • 6-6-10 正则表达式属性和方法

  • 总结

6-6-7 模式修正符

匹配模式(match mode)又被称之为模式修正符。 指的是匹配时使用的规则。 设置特定的模式,可能会改变对正则表达式的识别。
前面已经介绍过创建正则表达式对象时,可以设置 m i g 这三个标志,分别对应多行模式、不区分大小模式和全局模式三种。
i: 默认地,正则表达式是区分大小写的,通过设置标志 i ,可以忽略大小写(ignore case)。

  
    
    
  
  • console.log(/ab/.test("aB")); // false

  • console.log(/ab/i.test("aB")); // true

--
m: 默认地,正则表达式中的 ^ $ 匹配的是整个字符串的起始位置和结束位置,而通过设置标志 m ,开启多行模式,它们也能匹配字符串内部某一行文本的起始位置和结束位置。

  
    
    
  
  • console.log(/^b/.test('a\nb')); // false

  • console.log(/^b/m.test('a\nb')); // true

--
g: 默认地,第一次匹配成功后,正则对象就停止向下匹配了。 g 修饰符表示全局匹配(global),设置 g 标志后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。

  
    
    
  
  • console.log('1a,2a,3a'.replace(/a/,'b')); // 1b,2a,3a

  • console.log('1a,2a,3a'.replace(/a/g,'b')); // 1b,2b,3b

--

6-6-8 优先级

正则表达式千变万化,但是大多都是由之前介绍过的字符组、括号、量词等基本结构组合而成的。 这些元字符,和运算符一样拥有一个优先级关系,如下:
 
   
   
 
  • // 从上到下,优先级逐渐降低

  • \ 转义符

  • () (?!) (?=) [] 括号、字符组、环视

  • * + ? {n} {n,} {n,m} 量词

  • ^ $ 起始结束位置

  • | 选择

由于括号的用途之一就是为量词限定作用范围,所以优先级比量词高

  
    
    
  
  • console.log(/ab{2}/.test('abab')); // false

  • console.log(/(ab){2}/.test('abab')); // true

注意: 选择符 | 的优先级最低,比起始和结束位置都要低
 
   
   
 
  • console.log(/^ab|cd$/.test('abc')); // true

  • console.log(/^(ab|cd)$/.test('abc')); // false

  • console.log(/^(ab|cd)$/.test('ab')); // true

  • console.log(/^(ab|cd)$/.test('cd')); // true

--

6-6-9 局限性

   尽管 javascript 中的正则表达式功能比较完备,但与其他语言相比,缺少某些特性。 下面列出了 JavaScript 的正则表达式所不支持的特性。
  • POSIX 字符组(只支持普通字符组和排除型字符组)

  • Unicode支持(只支持单个Unicode字符)

  • 匹配字符串开始和结尾的\A和\Z锚(只支持^和$)

  • 逆序环视(只支持顺序环视)

  • 命名分组(只支持0-9编号的捕获组)

  • 单行模式和注释模式(只支持m、i、g)

  • 模式作用范围

  • 纯文本模式

--

6-6-10 正则表达式属性和方法

前面有提到,当我们使用 typeof 运算符来打印正则表达式的类型时,返回的是 object ,这说明正则表达式在 JavaScript 中也是一种对象。 那么既然是对象,就应该有相应的属性和方法。
1. 实例属性    每个 RegExp 实例对象都包含如下 5 个属性:
 
   
   
 
  • global布尔值,表示是否设置了 g 标志。

  • ignoreCase:布尔值,表示是否设置了 i 标志。

  • lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从 0 算起。

  • multiline:布尔值,表示是否设置了标志 m。

  • source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

示例如下:
 
   
   
 
  • let reg = /test/gi;

  • console.log(reg.global); // true

  • console.log(reg.ignoreCase); // true

  • console.log(reg.multiline); // false

  • console.log(reg.lastIndex); // 0

  • console.log(reg.source); // test

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

  • let reg = /\w/g;

  • let str = "abcd";

  • console.log(reg.lastIndex); // 0

  • console.log(reg.exec(str)); // [ 'a', index: 0, input: 'abcd' ]

  • console.log(reg.lastIndex); // 1

  • console.log(reg.exec(str)); // [ 'b', index: 1, input: 'abcd' ]

  • console.log(reg.lastIndex); // 2

  • console.log(reg.exec(str)); // [ 'c', index: 2, input: 'abcd' ]

  • console.log(reg.lastIndex); // 3

  • console.log(reg.exec(str)); // [ 'd', index: 3, input: 'abcd' ]

  • console.log(reg.lastIndex); // 4

  • console.log(reg.exec(str)); // null

  • console.log(reg.lastIndex); // 0

  • console.log(reg.exec(str)); // [ 'a', index: 0, input: 'abcd' ]

--
2. 构造函数属性(扩展)
RegExp 构造函数属性被看成静态属性,这些属性基于所执行的最近一次正则表达式操作而变化。
有 2 种方式访问它们,即长属性名和短属性名。 短属性名大都不是有效的 ECMAScript 标识符,所以必须通过方括号语法来访问它们。

  
    
    
  
  • 长属性名 短属性名     说明

  • input $_ 最近一次要匹配的字符串

  • lastMatch $& 最近一次的匹配项

  • lastParen $+ 最近一次匹配的捕获组

  • leftContext $` input字符串中lastMatch之前的文本

  • multiline $* 布尔值,表示是否所有表达式都使用多行模式

  • rightContext $' input字符串中lastMatch之后的文本

使用这些属性,可以从 exec() 方法或 test() 方法执行的操作中提取出更具体的信息
 
   
   
 
  • // test()用于测试一个字符串是否匹配某个正则表达式,并返回一个布尔值

  • let text = 'this has been a short summer';

  • let 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); // undefined

  • 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['$*']); // undefined

  • }

JavaScript 有 9 个用于存储捕获组的构造函数属性,在调用 exec() test() 方法时,这些属性会被自动填充。
注: 理论上,应该保存整个表达式匹配文本的 RegExp.$0 并不存在,值为 undefined。
 
   
   
 
  • // RegExp.$1,RegExp.$2,RegExp.$3...到 RegExp.$9 分别用于存储第一、第二……第九个匹配的捕获组

  • let text = 'this has been a short summer';

  • let pattern = /(..)or(.)/g;

  • if(pattern.test(text)){

  • console.log(RegExp.$1);//sh

  • console.log(RegExp.$2);//t

  • }

--
3. 实例方法    RegExp 对象的实例方法共 5 个,分为两类。 包括 toString() toLocalString() valueOf() 这3种对象通用方法和 test() exec() 这2种正则匹配方法
对象通用方法(扩展)
RegExp 对象继承了 Object 对象的 toString() toLocaleString() valueOf() 这 3 个通用方法。

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

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

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

注意: 不论正则表达式的创建方式是哪种,这三个方法都只返回其字面量形式
 
   
   
 
  • let pattern1 = new RegExp('[bc]at','gi');

  • console.log(pattern1.toString()); // '/[bc]at/gi'

  • console.log(pattern1.toLocaleString()); // '/[bc]at/gi'

  • console.log(pattern1.valueOf()); // /[bc]at/gi


  • let pattern2 = /[bc]at/gi;

  • console.log(pattern2.toString()); // '/[bc]at/gi'

  • console.log(pattern2.toLocaleString()); // '[bc]at/gi'

  • console.log(pattern2.valueOf()); // /[bc]at/gi

--
正则匹配方法
正则表达式 RegExp 对象的正则匹配方法只有两个: 分别是 test() exec()
test() 方法用来测试在字符串中是否能够找到符合正则要求的字符。 接收一个字符串参数,匹配时返回 true,否则返回 false。

  
    
    
  
  • let reg = /test/;

  • let str = "this is a test";

  • console.log(reg.test(str)); // true

在调用 test() 方法时,会造成 RegExp 对象的 lastIndex 属性的变化。
如果指定了全局模式,每次执行 test() 方法时,都会从字符串中的 lastIndex 偏移值开始尝试匹配。 所以用同一个 RegExp 多次验证相同字符串时,必须在每次调用之后,将 lastIndex 值置为 0。
 
   
   
 
  • let pattern = /^\d{4}-\d{2}-\d{2}$/g;

  • console.log(pattern.test('2016-06-23')); // true

  • console.log(pattern.test('2016-06-23')); // false

  • // 正确的做法应该是在验证不同字符串前,先将 lastIndex 重置为 0

  • let pattern = /^\d{4}-\d{2}-\d{2}$/g;

  • console.log(pattern.test('2016-06-23'));// true

  • pattern.lastIndex = 0;

  • console.log(pattern.test('2016-06-23'));// true

前面有介绍过,JavaScript有 9 个用于存储捕获组的构造函数属性,在调用 exec() test() 方法时,这些属性会被自动填充。
注意: 理论上,应该保存整个表达式匹配文本的 RegExp.$0 并不存在,值为 undefined
 
   
   
 
  • if(/^(\d{4})-(\d{2})-(\d{2})$/.test('2016-06-23')){

  • console.log(RegExp.$1); // '2016'

  • console.log(RegExp.$2); // '06'

  • console.log(RegExp.$3); // '23'

  • console.log(RegExp.$0); // undefined

  • }

exec() 方法专门为捕获组而设计,接受一个参数,即要应用模式的字符串。 然后返回包含匹配项信息的数组,在没有匹配项的情况下返回 null
在匹配项数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串,如果模式中没有捕获组,则该数组只包含一项。
返回的数组包含两个额外的属性: index input index 表示匹配项在字符串的位置, input 表示应用正则表达式的字符串。
 
   
   
 
  • let text = 'mom and dad and baby and others';

  • let pattern = /mom( and dad( and baby)?)?/gi;

  • let matches = pattern.exec(text);

  • console.log(pattern);

  • console.log(matches);

  • /*

  • /mom( and dad( and baby)?)?/gi

  • [ 'mom and dad and baby',

  • ' and dad and baby',

  • ' and baby',

  • index: 0,

  • input: 'mom and dad and baby and others',

  • groups: undefined ]

  • */

对于 exec() 方法而言,即使在模式中设置了全局标志 g ,它每次也只会返回一个匹配项。 在不设置全局标志的情况下,在同一个字符串上多次调用 exec() ,将始终返回第一个匹配项的信息。
 
   
   
 
  • let text = 'cat,bat,sat,fat';

  • let pattern1 = /.at/;

  • let matches = pattern1.exec(text);

  • console.log(pattern1,matches);

  • /*

  • * /.at/ [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]

  • */


  • let text = 'cat,bat,sat,fat';

  • matches = pattern1.exec(text);

  • console.log(pattern1,matches);

  • /*

  • * /.at/ [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]

  • */

而在设置全局标志的情况下,每次调用exec()都会在字符串中继续查找新匹配项。
 
   
   
 
  • let text = 'cat,bat,sat,fat';

  • let pattern2 = /.at/g;

  • let matches = pattern2.exec(text);

  • console.log(pattern2,matches);

  • /*

  • * /.at/g [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]

  • */


  • let text = 'cat,bat,sat,fat';

  • matches = pattern2.exec(text);

  • console.log(pattern2,matches);

  • /*

  • * /.at/g [ 'bat', index: 4, input: 'cat,bat,sat,fat' ]

  • */

注意: exec() 方法找出匹配的所有位置和所有值。
 
   
   
 
  • let string = 'j1h342jg24g234j 3g24j1';

  • let pattern = /\d/g;

  • let valueArray = []; // 值

  • let indexArray = []; // 位置

  • let temp;

  • while ((temp = pattern.exec(string)) != null) {

  • valueArray.push(temp[0]);

  • indexArray.push(temp.index);

  • }

  • console.log(valueArray);

  • console.log(indexArray);

  • // [ '1', '3', '4', '2', '2', '4', '2', '3', '4', '3', '2', '4', '1' ]

  • // [ 1, 3, 4, 5, 8, 9, 11, 12, 13, 16, 18, 19, 21 ]

总结

  1. JavaScript 里面对象是一组键值的集合。

  2. 访问对象的属性的方式有 3 种:点访问法,中括号访问法和 symbol 访问法。

  3. symbol 访问法是 ECMAScript 6 新添加的对象属性访问方式,主要就是为了避免属性名冲突的。

  4. 对象也可以进行嵌套和解构。

  5. 使用对象作为函数参数的技术被称之为命名参数,好处在于传参时参数顺序可以随意。

  6. this 的指向默认可以分为 2 种:指向全局对象和指向当前对象。

  7. 使用对象字面量来为一组函数创建一个命名空间可以解决命名冲突的问题。

  8. JSON 是一种轻量级的数据存储格式,它在人、机可读性方面达到了一个最佳的临界点。

  9. Math 对象是一个数学对象,提供了很多有用的属性和方法供我们使用。

  10. Date 对象主要用于处理和时间相关的操作。

  11. 正则表达式描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有某种子串,或者对匹配的子串进行替换、取出等操作。


以上就是今天的分享啦~
如果大家有问题或者想了解更多的
技术干货可以加朗妹儿微信哟~


往期精彩回顾




以上是关于JS基础——对象——正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

js基础(正则表达式)

JS基础 正则表达式

js入门篇之正则表达式基础

js入门篇之正则表达式基础

js正则表达式总结

js之正则表达式基础