JavaScript正则替换中$1、$2捕获组数据类型转换导致NaN的问题求助
我想给YouTube视频添加书签,现在有个需求:把带时分格式时间参数的YouTube链接,比如 https://www.youtube.com/watch?v=xxxxxx&t=12:13,转换成秒数格式的链接 https://www.youtube.com/watch?v=xxxxxx&t=733s(也就是把12:13转成12*60+13=733再加上s)。
我本来想一行代码搞定,还加了正则验证,写了这段JS代码:
let url = 'https://www.youtube.com/watch?v=xxxxxx&t=12:13'; console.log(url.replace(/(\d+)\:(\d+)/g, '$1$2')); let cUrl = url.replace(/(\d+)\:(\d+)/g, `${Number($1)*60 + Number($2)}s`); console.log(cUrl);
但浏览器控制台输出的结果里,cUrl显示的是NaN,我搞不懂哪里错了,能不能帮我看看问题出在哪?
浏览器控制台输出:

嘿,你这个问题我之前也踩过坑!问题出在你用模板字符串处理捕获组的方式上😯
你要知道,replace方法的替换值如果是字符串,$1、$2会被正则引擎识别为对应的捕获组内容;但如果用模板字符串,JS会先解析这个模板字符串,这时候$1和$2就是两个未定义的变量,Number($1)自然就变成NaN,最后计算结果肯定也是NaN了。
那怎么解决呢?把替换值改成一个回调函数就可以啦!replace的回调函数会接收匹配到的整个字符串、各个捕获组的内容作为参数,我们就能直接用这些参数来计算秒数:
let url = 'https://www.youtube.com/watch?v=xxxxxx&t=12:13'; // 正确的写法 let cUrl = url.replace(/(\d+)\:(\d+)/g, (_, minutes, seconds) => { return `${Number(minutes) * 60 + Number(seconds)}s`; }); console.log(cUrl); // 输出:https://www.youtube.com/watch?v=xxxxxx&t=733s
再给你掰扯清楚第一个replace为什么正常:因为你用的是字符串'$1$2',正则引擎会自动把$1替换成捕获到的分钟数12,$2替换成秒数13,所以输出1213是对的。但模板字符串不属于正则的替换规则范畴,JS会先处理模板字符串里的$1,这时候它根本不是正则捕获的分组,就导致了NaN的问题。
改成回调函数的写法后,就能正确拿到捕获组的数值进行计算,生成你想要的链接啦!
备注:内容来源于stack exchange,提问作者ArtBindu

