我正在尝试编写一个库来拦截所有 XMLHttpRequest 调用并在最终发送请求之前做一些事情,方法是覆盖其原型(prototype),例如:
var original_open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
// my own override logic here before running the original function
original_open.apply(this, arguments);
};
问题是,我想保证当有人使用这个库时,网页上的任何其他代码都不可能重新覆盖这个效果。
因为否则,使用这个库的网站可以动态加载另一段 JS 代码,它会再次简单地覆盖 XMLHttpRequest.prototype.open
,而这个库的全部目的就是禁止这样做。
我考虑过在覆盖后立即使用 Object.freeze()
卡住原型(prototype),这样其他代码就无法覆盖我自己的覆盖。代码看起来像这样:
var original_open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
// my own override logic here before running the original function
original_open.apply(this, arguments);
};
Object.freeze(XMLHttpRequest.prototype);
我的预期是,如果同一页面上的另一段代码试图重新覆盖我自己的覆盖,它将失败,因为原型(prototype)已被卡住。
我的问题:
- 这是这个问题的正确解决方案吗?
- 这真的安全吗? (没有漏洞)?
最佳答案
不要卡住原型(prototype)。这将导致开发人员感到沮丧、无法解释的错误,并且没有人使用您的库。您无法知道哪些其他库会修改该方法,以及它们将如何修改,这会导致您为无穷无尽的边缘情况编写代码。坚持最佳实践,并假设开发人员正在做出明智、兼容的库选择。
由于客户端代码的性质,您将不得不假设其他专业图书馆会遵循最佳实践。如果 5 个库都使用您使用的约定修改原型(prototype)方法,则所有 5 个库将协同工作。
例如,这两个覆盖只是一起工作:
var old1 = Document.prototype.querySelector;
Document.prototype.querySelector = function(...args) {
console.log('Override 1');
return old1.call(this, ...args);
};
var old2 = Document.prototype.querySelector;
Document.prototype.querySelector = function(...args) {
console.log('Override 2');
return old2.call(this, ...args);
};
let p = document.querySelector('body');
console.log(p);
关于javascript - 覆盖对象原型(prototype)并不允许任何进一步的覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47295812/