[英]Create a reset of javascript Array prototype when Array.prototype has been modified?
一般问题:当像 Array 这样的默认 Javascript 原型被修改、破解、更改和扭曲到无法使用的程度时,有没有办法创建(或重新实现)原始的、未修改的原型的实例?
我的情况:我有一些代码在(可怕的、专有的、封闭源代码的......)内容管理系统的“编辑”模式下失败,因为内容的“编辑”模式界面的 javascript管理系统从Array
原型中破解了绝对的人间地狱。
我的代码将在 CMS 的非编辑模式下工作,但要到达那里,它已经在“编辑”模式下进行了测试。 可以测试原型是否已被修改。 是否可以重新实现默认的 Array 原型,以便我可以执行以下操作:
var hasArrayBeenTrashed = // boolean based on https://stackoverflow.com/questions/574584/
var normalArray.prototype = // based on answer to this question
var myArray = !hasArrayBeenTrashed ? [] : new normalArray;
OP 现在可能已经想通了,但是对于从 Google 搜索或其他任何地方进入的任何其他人,这里有一个函数,它返回传递给它的任何默认构造函数的未修改版本:
// Note: the double name assignment below is intentional.
// Only change this part if you want to use a different variable name.
// │││││ The other one here needs to stay the same for internal reference.
// ↓↓↓↓↓ ↓↓↓↓↓
var reset = function reset(constructor) {
if (!(constructor.name in reset)) {
var iframe = document.createElement('iframe');
iframe.src = 'about:blank';
document.body.appendChild(iframe);
reset[constructor.name] = iframe.contentWindow[constructor.name];
document.body.removeChild(iframe);
} return reset[constructor.name];
}
问题
有人对默认原型做了一些愚蠢的事情......
Array.prototype.push = function () {
var that = this;
[].forEach.call(arguments, function (argument) {
that.splice(Math.round(Math.random()*that.length), 0, argument)
}); return 'Trolololo';
}
...您的代码变得一团糟。
var myArray = new Array(0, 1, 2, 3);
//-> undefined
// Ok, I made an array.
myArray;
//-> [0, 1, 2, 3]
// So far so good...
myArray.push(4, 5);
//-> "Trolololo"
// What?
myArray;
//-> [5, 0, 1, 2, 4, 3]
// WHAT!?
解决方案
所以你把这个功能混在一起......
var reset = function reset(constructor) {
if (!(constructor.name in reset)) {
var iframe = document.createElement('iframe');
iframe.src = 'about:blank';
document.body.appendChild(iframe);
reset[constructor.name] = iframe.contentWindow[constructor.name];
document.body.removeChild(iframe);
} return reset[constructor.name];
}
...并像这样使用它。
var myArray = new reset(Array)(0, 1, 2, 3);
//-> undefined
// Looks the same
myArray;
//-> [0, 1, 2, 3]
// Still looks the same
myArray.push(4, 5);
//-> 6
// Hey, it returned what it's supposed to...
myArray;
//-> [0, 1, 2, 3, 4, 5]
// ...and all's right with the world again!
此外,因为每个重置构造函数在第一次返回时都会被缓存,如果你想通过直接引用缓存( reset.Array
)而不是之后每次通过函数( reset(Array)
)来保存一个字符。
祝你好运!
您可以从 iframe 中复制 Array 方法:
Array.prototype.slice = function() {
return "trololol";
};
var a = document.createElement("iframe");
a.src = "about:blank";
document.body.appendChild(a);
var prototype = a.contentWindow.Array.prototype;
var fn = ["toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight"];
for (var i = 0; i < fn.length; ++i) {
var methodName = fn[i];
var method = prototype[methodName];
if (method) {
Array.prototype[methodName] = method;
}
}
document.body.removeChild(a);
这里是在chrome和IE9下工作的jsfiddle,没时间搞清楚IE7-8。 http://jsfiddle.net/jMUur/1/
在不依赖引用的情况下检查对象是否为数组:
function isArray( obj ) {
return {}.toString.call( obj ) === "[object Array]";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.