Javascript - проверить, был ли прототип метода изменен? - PullRequest
4 голосов
/ 22 февраля 2009

Какой лучший способ проверить, был ли изменен прототип метода?

Ответы [ 2 ]

9 голосов
/ 22 февраля 2009

Если вы выполняете toString () для функции, вы получаете исходный код функции. Для нативных функций FF, IE, Opera и Chrome возвращают функцию с телом [нативный код]. Тем не менее, Chrome имеет большинство функций, реализованных в javascript, и возвращает источник для большинства функций (Object.constructor является одной из немногих встроенных функций в Chrome, которая возвращает [native code])

Ниже вы найдете функцию с регулярным выражением, которая проверяет [собственный код]. (нет необходимости вызывать toString (), поскольку это делается автоматически, когда функция не вызывается). Он протестирован с FF3, IE7, Opera 9.6 и Chrome 1. Но, как я уже сказал, поскольку Chrome возвращает реальный исходный код для большинства функций, тестировать его в этом браузере бесполезно.

function isNative(func) {
    return /^\s*function[^{]+{\s*\[native code\]\s*}\s*$/.test(func);
}


alert(isNative(Array.prototype.push));

Обновление

Приведенный выше код, конечно, не обнаружит, если собственный метод будет заменен каким-либо другим собственным методом, таким как Array.prototype.push = Math.abs . Если вы хотите обнаружить изменения такого рода или если методы ваших собственных объектов были изменены, вы должны сохранить исходный метод в переменной, а затем запустить функцию, которая, как вы подозреваете, изменяет ее, а затем сравнить с сохраненными методами.

Однако после прочтения комментария к оператору olliej answer совершенно ясно, что ОП хотел знать, как определить, были ли изменены методы на собственных объектах , Если они изменяются, они обычно не заменяются другой встроенной функцией, но с новым кодом, обычно для добавления методов, которых у браузера нет изначально, или для изменения поведения в соответствии с ожидаемым стандартом. В этом случае приведенный выше код будет работать в FF, IE и Opera, но не в Crome.

Если вы хотите обнаружить какие-либо изменения методов, может пригодиться следующий код. Следующая функция создает объект двумя методами: save и сравни . save вызывается автоматически, если при создании объекта передаются аргументы. save ожидает два или более аргумента, где первый - это объект, а остальные - имена методов, которые будут сохранены. Причина, по которой вы должны предоставить имена методов, заключается в том, что большинство внутренних объектов имеет флаг " not enumerate ", установленный в методах.

function Cmpobj() {
    if (this.constructor !== arguments.callee){
        throw SyntaxError("Constructor called as function");
    }
    var srcobj, methods=[];
    this.save=function(obj) {
        var undef; //Local undefined
        srcobj=obj;
        for (var i=arguments.length -1; i>0; --i) {
            var name = arguments[i];
            //Push an object on the array without using push
            methods[methods.length] = {
                name:name,
                func:typeof obj[name] === "function" ? obj[name]:undef
            };
        }
    }
    this.compare=function(obj) {
        var changed=[];
        obj = obj || srcobj;
        for (var i=methods.length-1; i>=0; --i) {
            if (methods[i].func !== obj[methods[i].name]) {
                changed[changed.length]=methods[i].name;
            }
        }
        return changed;
    }
    if (arguments.length) this.save.apply(this,arguments);
}

// Creating a compare object. The first parameter is the object,
// followed by up to 254 method names.    
var saved = new Cmpobj(Array.prototype,"pop","push","slice");

//Do some change
Array.prototype.pop = Array.prototype.push;

// Compare if something is changed    
alert(saved.compare().join(", "));
2 голосов
/ 22 февраля 2009

Это зависит от того, что вы подразумеваете под «измененным», если вы имеете в виду изменение между моментом загрузки вашего кода и более поздним временем, вы можете просто сохранить ссылку на функцию, например

var oldFunc = SomeType.prototype.someFunction;
...
if (oldFunc === someInstance.someFunction) // unchanged, note the use of strict equality

Но если вы имеете в виду изменение по сравнению со стандартной реализацией по умолчанию, то нет никакого реального способа узнать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...