【问题标题】:Reverting overridden String prototype恢复被覆盖的字符串原型
【发布时间】:2023-12-26 12:43:01
【问题描述】:

我的 javascript 窗口中有一个重写的 String.prototype。

window.String.prototype.toUpperCase = ()=>{return "overridden"}

我有一个没有被触及的 iframe 窗口的引用,我想用它来创建一个没有被覆盖函数的新字符串:

console.log(iframe.contentWindow.String("newstring").toUpperCase());
// prints "overridden"

如何在没有覆盖函数的情况下创建新字符串?

对于使用新 iframe 覆盖的 Array.prototype,但不适用于 String

console.log(iframe.contentWindow.Array(1,2,3).filter(a=>a));
// that works - prints - [1,2,3]

注意

我知道不应该这样做。我在问如何在另一个 3rd 方库这样做的情况下修复它。

【问题讨论】:

标签: javascript string overriding


【解决方案1】:

问题是iframe.contentWindow.String("newstring") 只返回一个字符串,与 String("newstring") 或只是 "newstring" 评估的原始字符串相同。访问该字符串上的方法时,将使用当前领域中的 String.prototype,其中 toUpperCase 已损坏。

您需要创建一个实例来获得一个继承自 iframe 的String.prototypestring object

const stringObj = new iframe.contentWindow.String("newstring");
console.log(stringObj.toUpperCase());

但是,只恢复方法更容易:

String.prototype.toUpperCase = iframe.contentWindow.String.prototype.toUpperCase;
console.log("newstring".toUpperCase());

【讨论】:

  • @Yaron ...或者如果OP无法恢复该方法,OP可以基于calling原生String方法编写自己的upperCase函数...例如iframe.contentWindow.String.prototype.toUpperCase.call('foo')
【解决方案2】:

要恢复 JS 原生方法,您可以执行如下代码:

// Create dummy iframe to steal its fresh console object
const iframe = document.createElement('iframe');

// Add iframe to current window's scope in a hidden state
iframe.id = 'restoreiframe';
iframe.style.display = 'none';
iframe.name = 'restoreiframe_proxy'
document.body.insertAdjacentElement('beforeend', iframe);

// Reassign value of console to iframe's console
const proxyIframe = document.getElementsByName('restoreiframe_proxy')[0]; // document.getElementsByName

// restore document
document.getElementById = proxyIframe.contentDocument.getElementById;
document.getElementsByTagName = proxyIframe.contentDocument.getElementsByTagName;
document.getElementsByClassName = proxyIframe.contentDocument.getElementsByClassName;
document.querySelector = proxyIframe.contentDocument.querySelector;
document.querySelectorAll = proxyIframe.contentDocument.querySelectorAll;

// restore prototype
String.prototype.toUpperCase = proxyIframe.contentWindow.String.prototype.toUpperCase;

// remove proxy iframe
proxyIframe.remove();

【讨论】:

    最近更新 更多