大佬的demo,可以靠动态切换class改变盒子的形态
其中有一句正则:
var regExp = new RegExp('(?:^|\\s+)' + inClassName + '(?:\\s+|$)');
很明显用来匹配class中是否包含某个属性名的。用浅薄的正则知识仔细分析:
(开始位置有零次或一次的冒号 || 一个或多个\s) + 传参 + (零次或一次的冒号 || 一个或多个\s) 结尾要冒号做什么??
删除了第二个括号里的:后,控制台输出报错:/(?:^|\s+)className(?\s+|$)/: Invalid group连同?一并删除后,功能恢复正常。
查询后发现 ?:和()组合使用是非捕获分组的意思。
- ()表示捕获分组,()会把每个分组里的匹配的值保存起来,使用$n(n是一个数字,表示第n个捕获组的内容)
- (?:)表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来。
所以该正则基本等同于var regExp = new RegExp('(^|\\s+)' + inClassName + '(\\s+|$)');
开头和结尾有一个以上\s的className,或者className 只是不保存捕获组的结果。
问题是*是0或多次为什么不直接使用呢?于是改成这样
var regExp = new RegExp('(?:^\\s*)' + inClassName + '(?:\\s*$)');
失效了,F12查看元素,发现删除正则并没有匹配到。
经过一番尝试,把*放到捕获组外,整组重复0次或多次
var regExp = new RegExp('(?:^\\s)*' + inClassName + '(?:\\s$)*');
成功!
那么|\\s+和\\s*区别在哪里呢,于是用\\|s*尝试,成功。
结论:()内只有一个时,特殊字符要写在括号外才生效。
把生效的两个正则表达式再记录一遍:
var regExp = new RegExp('(?:^|\\s+)' + inClassName + '(?:\\s+|$)');
var regExp = new RegExp('(?:^\\s)*' + inClassName + '(?:\\s$)*');