当前位置 : 主页 > 大数据 > 区块链 >

当Array.prototype被修改时,创建一个javascript Array原型的重置?

来源:互联网 收集:自由互联 发布时间:2021-06-22
一般问题:当像Array这样的默认 Javascript原型被修改,被黑客攻击,改变和扭曲到不可用的时候,有没有办法创建(或重新实现)原始的未修改的原型? 我的情况:我有一些代码,在一个(可怕的
一般问题:当像Array这样的默认 Javascript原型被修改,被黑客攻击,改变和扭曲到不可用的时候,有没有办法创建(或重新实现)原始的未修改的原型?

我的情况:我有一些代码,在一个(可怕的,专有的,封闭的源…)内容管理系统的’编辑’模式失败,因为javascript的内容的“编辑”模式的界面管理系统打破了阵列原型的绝对生活.

我的代码将在CMS的非编辑模式下工作,但是要到达那里,它将在“编辑”模式下进行测试. It’s possible to test if a prototype has been modified.可以重新实现默认的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))来保存一个字符.

祝你好运!

网友评论