
用户脚本中用 .replace() 清除 steamcommunity.com/linkfilter/?u= 前缀后,目标链接却意外被浏览器补上前缀(当前页面 URL),根本原因是替换结果未以合法协议(如 https://)开头,导致浏览器误判为相对路径。
用户脚本中用 `.replace()` 清除 `steamcommunity.com/linkfilter/?u=` 前缀后,目标链接却意外被浏览器补上前缀(当前页面 url),根本原因是替换结果未以合法协议(如 `https://`)开头,导致浏览器误判为相对路径。
这个问题看似是字符串替换逻辑错误,实则是浏览器对 <a href></a> 属性值的URL 解析规范所致。当 JavaScript 动态设置 href 属性时,若新值不以标准协议(http://、https://、//、/、# 等)开头,浏览器会将其视为相对 URL,并自动相对于当前页面地址进行解析——这正是你看到 https://store.steampowered.com/... 被拼接到结果前端的根本原因。
? 关键线索在于:你在控制台中直接执行 .replace() 得到正确结果,是因为该操作仅返回纯字符串;而一旦赋值给 a.href(通过 .prop("href", ...)),DOM 就会触发完整的 URL 解析流程。
✅ 正确解决方案分两步:
-
确保替换后字符串是绝对 URL(即以
https://、http://或//开头); -
处理原始链接中可能存在的 URL 编码字符(如题中故意写成
https;实为规避审核,但真实场景中?u=后的 URL 常被encodeURIComponent()编码,例如https%3A%2F%2Fwww.cyberpunk.net)。
以下是修复后的稳健代码:
jQuery(document).on("mouseenter", "a", function(event) {
const $this = jQuery(this);
let href = $this.prop("href");
// 匹配 linkfilter 重定向链接(支持编码与非编码两种形式)
const filterRegex = /^https?:\/\/steamcommunity\.com\/linkfilter\/\?u=(.+)$/;
const match = href.match(filterRegex);
if (match && match[1]) {
try {
// 先解码(兼容 encoded URI),再验证是否为合法绝对 URL
let target = decodeURIComponent(match[1]);
// 强制标准化协议前缀:补全 https:// 若缺失(如出现 'www.cyberpunk.net')
if (/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/.test(target) && !/^https?:\/\//.test(target)) {
target = 'https://' + target;
}
// ✅ 关键:仅当 target 是合法绝对 URL 时才赋值,避免相对路径陷阱
if (/^https?:\/\//.test(target)) {
$this.prop("href", target);
}
} catch (e) {
// 解码失败则跳过,保留原链接
console.warn("Failed to decode linkfilter URL:", href, e);
}
}
});⚠️ 注意事项:
- 不要使用
.attr("href")替代.prop("href"):attr()返回原始 HTML 属性值(含编码),prop()返回解析后的 DOM 属性值(已解码),此处需基于解析后的真实 URL 操作; - 避免正则中硬编码
https;—— 这是人为规避检测的写法,实际生产环境应匹配标准https?://; - 若网站使用 CSP 限制
eval或动态脚本,确保用户脚本注入时机早于链接渲染(可加@run-at document-idle或document-start声明); - 推荐在 Tampermonkey 中启用
@grant none模式(默认),避免因沙箱隔离导致decodeURIComponent失效。
? 扩展建议:
如需更高可靠性,可结合 new URL() 构造器做校验(现代浏览器支持):
try {
const url = new URL(target);
if (url.protocol === 'http:' || url.protocol === 'https:') {
$this.prop("href", url.href); // 自动标准化格式
}
} catch (e) {
// 非法 URL,不修改
}总之,这不是 jQuery 或 replace 的 Bug,而是 Web 平台对超链接语义的严格遵循。理解浏览器如何解析 href,才能写出真正健壮的链接净化脚本。

















