我试图编写一个拦截所有XMLHttpRequest调用的库,并在最终通过覆盖其原型之前做一些事情,例如:
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()
冻结原型,这样其他代码就无法覆盖我自己的覆盖。代码看起来像这样:
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);
我的期望是,如果同一页面上的另一段代码试图重新覆盖我自己的覆盖,它将失败,因为原型已被冻结。
答案 0 :(得分:1)
不要冻结原型。这会导致开发人员感到沮丧,无法解释的错误以及没有人使用您的库。您无法知道其他库将修改该方法,以及它们将如何执行此操作,从而导致您编写无穷无尽的边缘情况。坚持最佳实践,并假设开发人员正在进行明智,兼容的库选择。
由于客户端代码的性质,您必须假设其他专业图书馆将遵循最佳做法。如果5个库都使用您使用的约定修改原型方法,则所有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);