JavaScript用户脚本中如何为黑盒函数updateBOB添加回调或重定义?
这个问题我之前也碰到过!核心原因是用户脚本的沙箱隔离机制——你在脚本里修改的updateBOB其实是沙箱里的副本,网站实际调用的是全局作用域里的原始函数,所以你的重写根本没生效。下面给你几个可行的解决思路:
方案1:直接修改全局作用域的updateBOB(Tampermonkey/Greasemonkey 4+ 适用)
如果你的用户脚本管理器支持unsafeWindow(比如Tampermonkey),可以通过它直接访问网站的全局变量,这样修改的就是真正被网站调用的updateBOB了:
$(document).ready(function() { // 初始添加按钮 addButton(); // 拿到全局作用域里的原始updateBOB const originalUpdateBOB = unsafeWindow.updateBOB; // 重写全局的updateBOB unsafeWindow.updateBOB = function() { // 先执行网站原本的更新逻辑 originalUpdateBOB.apply(this, arguments); // 重新添加按钮 addButton(); }; }); function addButton() { // 避免重复添加,先检查按钮是否存在 if (!document.getElementById('my-custom-btn')) { const btn = document.createElement('button'); btn.id = 'my-custom-btn'; btn.textContent = '我的自定义按钮'; // 替换成你实际要插入的位置 document.body.appendChild(btn); } }
方案2:注入代码到页面全局作用域(通用兼容)
如果你的脚本管理器不支持unsafeWindow,或者想要更通用的方案,可以把重写函数的代码注入到页面的<script>标签里——这样代码会直接运行在网站的全局作用域中,能精准修改目标函数:
$(document).ready(function() { // 初始添加按钮 addButton(); // 生成注入用的脚本内容 const scriptContent = ` const originalUpdateBOB = window.updateBOB; window.updateBOB = function() { originalUpdateBOB.apply(this, arguments); // 调用全局暴露的添加按钮函数 window.myCustomAddButton(); }; `; // 创建并注入脚本标签 const script = document.createElement('script'); script.textContent = scriptContent; document.head.appendChild(script); // 注入后移除标签,避免污染DOM script.remove(); // 把addButton暴露到全局,让注入的代码能调用 window.myCustomAddButton = addButton; }); function addButton() { if (!document.getElementById('my-custom-btn')) { const btn = document.createElement('button'); btn.id = 'my-custom-btn'; btn.textContent = '我的自定义按钮'; document.body.appendChild(btn); } }
兜底方案:用MutationObserver监听DOM变化
如果网站把updateBOB封装在闭包里,导致你无法直接访问到它,那可以用MutationObserver监听DOM变化——当你的按钮被移除时,自动重新添加:
$(document).ready(function() { addButton(); // 创建观察者,监听按钮所在容器的DOM变化 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // 检查是否有节点被移除 if (mutation.removedNodes.length > 0) { const btn = document.getElementById('my-custom-btn'); // 如果按钮不存在了,重新添加 if (!btn) addButton(); } }); }); // 监听body下的所有子节点变化(可以替换成按钮所在的具体父容器) observer.observe(document.body, { childList: true, subtree: true }); }); function addButton() { if (!document.getElementById('my-custom-btn')) { const btn = document.createElement('button'); btn.id = 'my-custom-btn'; btn.textContent = '我的自定义按钮'; document.body.appendChild(btn); } }
内容的提问来源于stack exchange,提问作者NoodleSkadoodle
相关产品推荐
相关产品推荐

