如何重写JavaScript函数?第三方Guestplan插件函数重写失败求助
解决重写外部插件
_gstpln.openWidget/closeWidget函数的问题 你的问题核心在于异步脚本加载的时机,以及插件可能对这些方法的后续赋值覆盖。我给你几个可行的解决思路:
1. 监听插件脚本加载完成后再重写(最可靠)
因为你初始化插件时用了async=1,脚本是异步加载的——这意味着你之前在$(document).ready或者初始化脚本末尾的赋值,大概率在插件脚本还没加载完成时就执行了,此时_gstpln上的closeWidget和openWidget还没被插件定义,等插件加载完成后,它会自己给_gstpln添加这些方法,直接覆盖了你之前的修改。
修改初始化脚本,在脚本的onload回调里执行重写逻辑:
(function(g,s,t,p,l,n){ g["_gstpln"]={}; (l=s.createElement(t)),(n=s.getElementsByTagName(t)[0]); l.async=1; l.src=p; // 等插件脚本加载完成后再重写方法 l.onload = function() { // 先保存原函数,避免丢失原有功能 const originalClose = _gstpln.closeWidget; _gstpln.closeWidget = function() { // 这里添加你的自定义逻辑 console.log('执行自定义关闭逻辑'); // 调用原函数(如果需要保留原有功能的话) originalClose.apply(this, arguments); }; // 同理处理openWidget const originalOpen = _gstpln.openWidget; _gstpln.openWidget = function() { console.log('执行自定义打开逻辑'); originalOpen.apply(this, arguments); }; }; n.parentNode.insertBefore(l,n); })(window,document,"script","https://cdn.guestplan.com/widget.js"); // 初始化配置保持不变 _gstpln.accessKey = "cebd85865b61ba61961cc749c8ca02e43cad6535"; _gstpln.color = "#000000"; _gstpln.showFab = false;
2. 使用Proxy代理拦截方法调用
如果插件内部用闭包封装了方法,直接修改_gstpln的属性可能无效,这时可以用ES6的Proxy来拦截对这些方法的访问:
(function(g,s,t,p,l,n){ g["_gstpln"]={}; (l=s.createElement(t)),(n=s.getElementsByTagName(t)[0]); l.async=1; l.src=p; l.onload = function() { window._gstpln = new Proxy(window._gstpln, { get(target, prop) { // 拦截closeWidget调用 if (prop === 'closeWidget') { return function() { // 自定义逻辑 console.log('自定义关闭动作'); // 调用原方法 return target[prop].apply(target, arguments); }; } // 拦截openWidget调用 if (prop === 'openWidget') { return function() { console.log('自定义打开动作'); return target[prop].apply(target, arguments); }; } // 其他属性直接返回原对象的值 return target[prop]; } }); }; n.parentNode.insertBefore(l,n); })(window,document,"script","https://cdn.guestplan.com/widget.js"); // 初始化配置不变 _gstpln.accessKey = "cebd85865b61ba61961cc749c8ca02e43cad6535"; _gstpln.color = "#000000"; _gstpln.showFab = false;
3. 轮询检测方法是否存在(兼容旧环境)
如果你需要兼容不支持Proxy的旧浏览器,可以用定时器轮询,直到_gstpln的目标方法存在再重写:
$(document).ready(function() { const checkInterval = setInterval(() => { // 确认目标方法已被插件定义 if (window._gstpln && typeof window._gstpln.closeWidget === 'function') { // 重写closeWidget const originalClose = window._gstpln.closeWidget; window._gstpln.closeWidget = function() { console.log('自定义关闭逻辑'); originalClose.call(this, ...arguments); }; // 重写openWidget const originalOpen = window._gstpln.openWidget; window._gstpln.openWidget = function() { console.log('自定义打开逻辑'); originalOpen.call(this, ...arguments); }; // 停止轮询 clearInterval(checkInterval); } }, 100); // 每隔100ms检查一次,可根据实际调整间隔 });
额外建议
先查看插件的官方文档,看是否提供了官方的事件回调(比如onWidgetOpen、onWidgetClose),如果有的话,优先使用官方API,这样更稳妥,也避免插件更新后你的重写逻辑失效。
内容的提问来源于stack exchange,提问作者hans
相关产品推荐
相关产品推荐

