巴扎黑2017-04-10 14:41:29 0 2 129
代码如下:
'z/yy'.replace(/\/(y|z)|y|z/g, function(name, index) {
console.log(index, name.length);
return name == 'y' || name == 'z' ? 'a' : name;
});
正确输出:a/ya
'z/yy'.replace(/\/(y|z)|\1/g, function(name, index) {
console.log(index, name.length);
return name == 'y' || name == 'z' ? 'a' : name;
});
错误输出:z/yy
请问为什么呢?
黄舟 2017-04-10 14:43:292楼
@皓矾 的console解释的比较清楚了,唯一不同意的地方是|\1不是匹配所有字符串,而是0长空字符。console里可以看出来。
这里/\/(y|z)|\1/是分为两个正则分别匹配的:
1. \/(y|z) 捕获组1是括号中y|z匹配的内容。比如/(y|z)\1/ 匹配yy,zz,但是不匹配yz
2. \1 捕获组1未定义
所以2中的\1不会如你所想的匹配y或z
比较符合你意图的写法可能是
/\/?(y|z)/
赞 +0添加回复
小皮 2017-04-10 14:43:291楼
这两个正则是不等价的。
第一个
/\/(y|z)|y|z/g
,分解开来是\/(y|z)
或y
或z
。所以,对于字符串z/yy
,第一个字符z
匹配,被替换为a
,/y
符合但不等于y
或z
,所以原样输出为/y
,最后一个z
同理替换为a
。第二个
/\/(y|z)|\1/g
,比较复杂,展开来说。在此之前,先根据MDN的文档重写下函数,因为题主的参数不太正确:
其中,
matcher
是匹配的子字符串,p1
是捕捉组匹配的子字符串,既(y|z)
捕捉到的,offset
是偏移值,str
是原字符串。执行结果如下:
一步步来,
z/yy
,matcher
为空,未匹配。/yy
,matcher
为/y
,捕捉到y
。但题主的返回值判断的是matacher
与y
和z
的比较,所以原样返回/y
。y
,matcher
为空,未匹配。matcher
为空,未匹配。关键在第三行,对于字符串'y',正则仍然是
/\/(y|z)|\1/g
,而不是题主所想的/\/(y|z)|(y|z)/g
,所以不匹配。顺带研究了下这种
|\1
写法的正则,这种写法貌似会匹配任何字符串,甚至空字符串。比如:甚至:
所以,最好还是别这样写……
赞 +0添加回复