适配Microsoft Edge和Safari的Regex环视替代方案怎么实现?
不兼容原因
你用的正则包含两个ES2018才新增的特性,旧版Edge(EdgeHTML内核,42版本属于该类)、低于11.1版本的Safari都不支持:
- 负向零宽后行断言
(?<!...) - Unicode属性转义
\p{}
兼容方案
将后行断言的排除逻辑替换为「前置匹配+分组捕获」即可实现完全等价的匹配效果,无需修改业务逻辑核心:
1. 调整正则构造规则
原逻辑是匹配「前面不存在禁止字符的关键词」,我们改成匹配「字符串开头/合法前置字符 + 关键词」,再单独提取关键词部分即可:
// 前置规则:匹配字符串开头,或者不属于禁止范围的前置字符 const prefixRule = '(^|[^\\p{L}\\p{M}\\p{N}_-])' // 关键词匹配、后缀负向断言逻辑保持不变,负向前行断言兼容性极强,旧浏览器均支持 const keywordRule = '(?:' + keywords.map(escapeRegExp).join('|') + ')' const suffixRule = '(?![\\p{L}\\p{N}_-])' var pattern = new RegExp(prefixRule + keywordRule + suffixRule, 'igu')
2. 适配匹配结果处理逻辑
原来直接使用完整匹配结果,现在要把前置匹配的字符剥离,只保留关键词部分:
// 原高亮逻辑示例 // text = text.replace(pattern, match => `<span class="highlight">${match}</span>`) // 兼容写法,prefix是匹配到的前置字符,剥离后即可得到目标关键词 text = text.replace(pattern, (match, prefix) => { const keyword = match.slice(prefix.length) return `${prefix}<span class="highlight">${keyword}</span>` })
更低版本兼容(可选)
如果你的业务只需要处理英文、数字,不需要支持多语言匹配,可以把Unicode属性转义替换为ASCII范围,同时去掉u修饰符,可兼容更古老的浏览器:
var pattern = new RegExp('(^|[^a-zA-Z0-9_-])(?:' + keywords.map(escapeRegExp).join('|') + ')(?![a-zA-Z0-9_-])', 'ig')
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

