拦截修改动态加载script标签innerHTML后,如何同步至DOM原生属性?
解决HTMLScriptElement的innerHTML拦截与原始值保存问题
问题分析
你已经成功拦截了script标签的innerHTML赋值操作,但之前的两种尝试都存在问题:
- 直接修改
HTMLElement.prototype.innerHTML:此时this指向的是HTMLElement.prototype而非当前的script实例,不符合DOM属性的调用上下文要求,因此触发"illegal invocation"错误。 - 直接修改
HTMLScriptElement.prototype.innerHTML:会递归触发你自定义的setter,导致栈溢出("Maximum call stack size exceeded")。
正确实现方式
核心思路是先保存原始的innerHTML setter,再在自定义setter中调用它并传入修改后的值,同时确保调用时绑定当前的script实例作为上下文:
// 保存HTMLElement原型上的原始innerHTML setter const originalInnerHTMLSetter = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerHTML').set; // 重新定义HTMLScriptElement的innerHTML属性 Object.defineProperty(HTMLScriptElement.prototype, "innerHTML", { set: function (value) { // 修改赋值内容 const modifiedValue = value + 1; console.log(modifiedValue); // 调用原始setter,绑定当前实例作为this originalInnerHTMLSetter.call(this, modifiedValue); }, // 保留原始getter,确保读取时能拿到正确值 get: Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerHTML').get });
验证效果
执行以下测试代码:
const o = document.createElement('script'); o.innerHTML = 1; console.log(o.innerHTML); // 输出"2",在DOM中查看该script标签内容也会显示"2"
这样既完成了赋值操作的拦截与修改,又能将修改后的值正确保存到DOM元素中,同时规避了之前的错误。
内容的提问来源于stack exchange,提问作者Gianluca De Stefano
相关产品推荐
相关产品推荐

