简体   繁体   English

Javascript - 检查方法原型是否已更改?

[英]Javascript - check if method prototype has been changed?

检查方法原型是否已更改的最佳方法是什么?

If you do a toString() on a function you get the source code of the function. 如果在函数上执行toString(),则会获得函数的源代码。 For native functions, FF, IE, Opera and Chrome returns a function with the body [native code]. 对于原生函数,FF,IE,Opera和Chrome返回一个带有正文[本机代码]的函数。 However, Chrome has most functions implemented in javascript and will return the source for most functions (Object.constructor is one of the few native functions in Chrome that does return [native code]) 但是,Chrome的大部分功能都是用javascript实现的,并且会返回大多数函数的源代码(Object.constructor是Chrome中为数不多的返回[本机代码]的本机函数之一)

Below you find a function with a regexp that checks for [native code]. 下面是一个带有正则表达式的函数,用于检查[本机代码]。 (there is no need to call toString() since it is done automatically when the function isn't called). (不需要调用toString(),因为它在未调用函数时自动完成)。 It is tested with FF3, IE7, Opera 9.6 and Chrome 1. But as I said, since Chrome does return the real source code for most functions it isn't useful to test it in that browser. 它使用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));

Update 更新

The above code will of course not detect if a native method is replaced with some other native method, like Array.prototype.push = Math.abs . 上面的代码当然不会检测本机方法是否被其他一些本机方法替换,如Array.prototype.push = Math.abs If you want to detect that kind of change, or if methods of your own objects are changed, you must store the original method in a variable, then run the function that you suspect changes it, followed by a compare with the stored methods. 如果要检测那种更改,或者更改了自己对象的方法,则必须将原始方法存储在变量中,然后运行您怀疑更改它的函数,然后与存储的方法进行比较。

However, after reading the comment from the op on olliej answer , it is quite clear that the OP wanted to know how to detect if methods on the native objects has been changed. 但是,在阅读了关于olliej 回答的op的评论之后,很明显OP想知道如何检测本机对象上的方法是否已经改变。 If they are changed they are usually not replaced with another native function but with some new code, usually to add methods that the browser don't have natively, or to change the behavior to be compatible with the expected standard. 如果它们被更改,它们通常不会被另一个本机函数替换,而是使用一些新代码,通常是添加浏览器本身没有的方法,或者更改行为以与预期标准兼容。 In that case the code above will work in FF, IE and Opera but not Crome. 在这种情况下,上面的代码将在FF,IE和Opera中运行,但不适用于Crome。

If you want to detect any type of changes of the methods the following code might be of use. 如果要检测方法的任何类型的更改,可能会使用以下代码。 The following function creates an object with two methods: save and compare . 以下函数使用两种方法创建对象: savecompare save is automatically called if arguments is supplied when the object is created. 如果在创建对象时提供了参数,则会自动调用save save expects two or more arguments where the first is the object and the rest is the method names to be saved. save需要两个或多个参数,其中第一个是对象,其余是要保存的方法名称。 The reason you must supply the names of the methods is because most internal objects has the " do not enumerate "-flag set on the methods. 您必须提供方法名称的原因是因为大多数内部对象在方法上设置了“ 不要枚举 ”-flag。

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(", "));

It depends on what you mean by "changed" if you mean changed between when your code gets loaded and some later time, you can just store a reference to the function, a la如果您的意思是在代码加载时和稍后的时间之间更改,则取决于您所说的“更改”是什么意思,您可以只存储对该函数的引用,即

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

But if you mean changed from the default native implementation there's no real way to tell.但是,如果您的意思是从默认的本机实现更改,则没有真正的方法可以分辨。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM