Javascript - vérifier si le prototype de méthode a été changé?


3

Quelle est la meilleure méthode pour vérifier si le protoype d'une méthode a été changé?

8

Si vous faites un toString() sur une fonction, vous obtenez le code source de la fonction. Pour les fonctions natives, FF, IE, Opera et Chrome renvoie une fonction avec le corps [code natif]. Cependant, Chrome a la plupart des fonctions implémentées en javascript et retournera la source pour la plupart des fonctions (Object.constructor est l'une des rares fonctions natives dans Chrome qui retourne [code natif])

Ci-dessous vous trouvez une fonction avec une regexp qui vérifie le [code natif]. (il n'est pas nécessaire d'appeler toString() car cela se fait automatiquement lorsque la fonction n'est pas appelée). Il est testé avec FF3, IE7, Opera 9.6 et Chrome 1. Mais comme je l'ai dit, puisque Chrome renvoie le vrai code source pour la plupart des fonctions, il n'est pas utile de le tester dans ce navigateur.

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


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

Mise à jour

Le code ci-dessus bien sûr ne pas détecter si une méthode native est remplacée par une autre méthode native, comme Array.prototype.push = Math.abs. Si vous souhaitez détecter ce type de modification ou si les méthodes de vos propres objets sont modifiées, vous devez stocker la méthode d'origine dans une variable, puis exécuter la fonction que vous suspectez, puis la comparer aux méthodes stockées. Cependant, après avoir lu le commentaire de l'op olliejanswer, il est tout à fait clair que l'OP voulait savoir comment détecter si les méthodes sur les objets natifs avaient été modifiées. Si elles sont changées, elles ne sont généralement pas remplacées par une autre fonction native mais par un nouveau code, généralement pour ajouter des méthodes que le navigateur n'a pas en natif, ou pour changer le comportement pour qu'il soit compatible avec le standard attendu. Dans ce cas, le code ci-dessus fonctionnera dans FF, IE et Opera mais pas Crome.

Si vous souhaitez détecter tout type de modification des méthodes, le code suivant peut être utile. La fonction suivante crée un objet avec deux méthodes: enregistrer et comparer. save est automatiquement appelée si des arguments sont fournis lors de la création de l'objet. save attend deux arguments ou plus où le premier est l'objet et le reste est les noms de méthodes à enregistrer. La raison pour laquelle vous devez fournir les noms des méthodes est que la plupart des objets internes ont le paramètre "n'énumère pas" sur les méthodes.

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

Cela ne fonctionne pas si vous faites 'Array.push = Math.abs' c'est pourquoi je ne l'ai pas suggéré dans ma réponse. 22 févr.. 092009-02-22 23:16:53

  0

@olliej: C'était implicite, mais j'ai quand même mis à jour la réponse. 23 févr.. 092009-02-23 04:24:52


2

Cela dépend de ce que vous entendez par « changé » si vous voulez dire changé entre le moment où votre code est chargé et quelque temps plus tard, il vous suffit de stocker une référence à la fonction, à la

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

Mais si vous voulez dire changé de l'implémentation native par défaut, il n'y a pas de véritable moyen de le dire.

  0

Ainsi, certaines bibliothèques comme Prototype modifient les prototypes d'objets de base, comme Array.prototype.push ou pop. Je me demande donc comment vous pouvez vérifier si la méthode prototype par défaut pour un objet natif a été modifiée. 22 févr.. 092009-02-22 10:19:49