同源场景下如何重写iframe的window.close和window.open方法?
失效原因
- 代码执行时机早于iframe加载完成:iframe加载过程中会初始化自身的window全局对象,提前修改的属性会被后续加载的原生属性覆盖
- 原生
window.close、window.open是浏览器内置的低可写性属性,直接赋值在多数场景下不会生效
正确实现方案
方案1:父窗口监听iframe加载完成后修改(无需改动iframe内容)
通过监听iframe的load事件确保修改时iframe的window对象已完全初始化,同时使用Object.defineProperty绕过原生属性的可写性限制:
const iframe = document.querySelectorAll('iframe')[0]; // 注意:如果是动态设置iframe.src,请将src赋值放在load事件绑定之后,避免漏触发load事件 iframe.addEventListener('load', () => { const winIframe = iframe.contentWindow; // 重写window.close Object.defineProperty(winIframe, 'close', { value: () => { alert('close'); // 如需保留原生关闭逻辑,可补充调用:winIframe.close.call(winIframe) }, writable: false, configurable: false }); // 重写window.open Object.defineProperty(winIframe, 'open', { value: (...args) => { alert('open'); // 如需保留原生打开逻辑,可补充返回:return winIframe.open.apply(winIframe, args) }, writable: false, configurable: false }); });
方案2:iframe内部直接重写(兼容性最高)
如果可以控制iframe的页面内容,直接在iframe内部的脚本中重写对应方法即可,不会出现时机冲突问题:
// 写在iframe页面内的script标签中 window.close = () => { alert('close'); }; window.open = () => { alert('open'); };
以上两种方案仅在同源场景下生效,跨域场景受浏览器安全限制无法操作iframe内部window对象。
内容的提问来源于stack exchange,提问作者ar099968
相关产品推荐
相关产品推荐

