JS如何实现将页面中属于指定数组的所有匹配单词文字改为红色
问题原因
你的代码存在3个核心问题:
- 每次替换都基于最开始保存的原始HTML字符串,没有同步更新该变量,前序替换结果会被后续操作直接覆盖
- 插入带样式的标签后,HTML字符串长度发生变化,基于原始字符串计算的匹配索引全部失效
- 直接传入字符串调用
matchAll不会开启全局匹配,只会返回第一个匹配结果
优化后的实现方案
推荐直接用全局正则替换实现,逻辑更简洁,也能规避索引偏移的问题,修改后的JS代码如下:
// 可选:如果搜索词包含. + *等正则特殊字符,需要先调用该方法转义 function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function change() { const body = document.querySelector("body"); // 提取所有纯文本节点,避免误修改HTML标签属性、script标签内的内容 const textNodes = []; const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_TEXT, null); let currentNode; while (currentNode = nodeIterator.nextNode()) { if (currentNode.parentElement.tagName !== 'SCRIPT') { textNodes.push(currentNode); } } const searching = ["Lorem","nemo"]; // 遍历每个文本节点单独替换 textNodes.forEach(node => { let text = node.textContent; searching.forEach(keyword => { // 构建全局匹配正则 const reg = new RegExp(escapeRegExp(keyword), 'g'); text = text.replace(reg, `<span style="color: red;">$&</span>`); }); // 替换原文本节点为带样式的新内容 const tempDiv = document.createElement('div'); tempDiv.innerHTML = text; while (tempDiv.firstChild) { node.parentNode.insertBefore(tempDiv.firstChild, node); } node.remove(); }); } change();
代码说明
- 用
document.createNodeIterator筛选纯文本节点,不会误改标签属性、JS代码里的同名字符串 - 全局正则
g修饰符会匹配当前文本节点内所有对应关键词,$&指代匹配到的原文内容 - 每个文本节点单独处理,不会出现匹配位置偏移的问题
内容的提问来源于stack exchange,提问作者iamhimanshu0
相关产品推荐
相关产品推荐

