2010-10-27 18 views
1

Donc, je voudrais avoir du code exécuté à chaque fois qu'une fonction donnée est appelée, est-ce faisable? La chose est, je pourrais juste écraser la fonction existante et ajouter le code, mais cela exigerait que je connaisse le contenu exact de cette fonction ... Imaginez un "plug-in" à une "bibliothèque", et vous voulez le plug- pour exécuter du code chaque fois qu'une fonction spécifique de cette bibliothèque est appelée, mais vous ne voulez pas écraser le contenu original de la bibliothèque ... J'espère que je suis assez clair!Javascript: Comment puis-je exécuter du code sur un appel de fonction sans écraser cette fonction?

Et si c'est faisable, existe-t-il un moyen de récupérer les arguments soumis à la fonction?

+0

Dans [aspect orienté] (http://en.wikipedia.org/wiki/Aspect-oriented_programming) et (http://en.wikipedia.org/wiki/Functional_programming) [fonctionnelle] la programmation, ce que vous demandez est appelé ["conseil"] (http://en.wikipedia.org/wiki/Advice_%28programming%29). – outis

Répondre

1

Il est certainement faisable. JS est un langage dynamique, vous pouvez donc échanger une fonction stockée dans un objet avec la vôtre. Par exemple:

var fxnToWrap = obj.someFunction; 
obj.someFunction = function() { 
    console.log("booyah, I'm intercepting every call to obj.someFunction"); 
    fxnToWrap.apply(obj, arguments); 
} 
+0

C'est exactement ce que je cherchais! Je ne connaissais pas .apply(), semble être très utile pour moi, merci! – Alex

+0

Je suis presque sûr que l'avant-dernière ligne devrait être fxnToWrap.apply (obj, arguments); puisque le premier argument à appliquer définit le contexte dans lequel la fonction s'exécute (c'est-à-dire ce qui sera assigné à cela). En le mettant à obj, le func pourra l'utiliser pour accéder aux propriétés et méthodes de l'objet. –

+0

@Sid_M Vous avez raison! Fixé. – kevingessner

1

Vous pourriez éventuellement écraser la référence à la fonction? Par exemple:

function add1(x) { return x + 1; } 
function log_calls(f, name) { 
    return function() { 
     console.log("got a call to", name, "with args", arguments); 
     return f.apply(null, arguments); 
    } 
} 
add1 = log_calls(add1, "add1"); 

appelle ensuite à add1 serait quelque chose comme:

>> x = add1(42) 
"got call to add1 with args [42]" 
>> x 
43 
+0

Est-ce que j'ai besoin, merci. – Alex

3

Sonne comme un emploi pour une fonction wrapper pour moi.

Ecrivez une fonction qui appelle l'autre fonction et placez votre code à la fin de celle-ci (ou ailleurs). Alors appelez toujours votre version à la place.

Sorte de motif d'adaptateur. Je crois que vous pouvez masquer la portée de la fonction d'origine et nommez la même chose si vous ne pouvez pas modifier le code appelant (ne fonctionne pas sur certaines fonctions intrinsèques comme l'alerte, mais devrait fonctionner pour le code de la bibliothèque). Si ce n'est pas une option, voyez si prototype vous permettra d'étendre l'objet pour ajouter la fonctionnalité. http://phrogz.net/js/classes/ExtendingJavaScriptObjectsAndClasses.html

//Only add this implementation if one does not already exist. 
if (Array.prototype.slice==null) Array.prototype.slice=function(start,end){ 
    if (start<0) start=this.length+start; //'this' refers to the object to which the prototype is applied 
    if (end==null) end=this.length; 
    else if (end<0) end=this.length+end; 
    var newArray=[]; 
    for (var ct=0,i=start;i<end;i++) newArray[ct++]=this[i]; 
    return newArray; 
} 

Pour arguments, vous pouvez également prendre votre version des arguments optionnels (similaires à jQuery/MooTools), puis regarder ce qui a été adopté.

Exemples d'arguments optionnels ici. http://www.openjs.com/articles/optional_function_arguments.php

function accident() { 
    for(var i = 0; i < arguments.length; i++) { 
     alert("This accident was caused by " + arguments[i]); 
    } 
} 
+0

Merci pour votre réponse! Je vais prendre un peu de lecture de tout ça, mais les arguments peu à la fin de votre post sont vraiment utiles, jamais utilisés auparavant;). Je n'ai pas compris ce que les trucs de tableau avaient à faire avec mon probelm cependant? Juste une "démo" sur la façon d'utiliser un prototype? – Alex

+0

Oui, il est copié à partir du lien que j'ai posté juste au-dessus dans le cadre de la démo sur prototype; ils ajoutent une fonctionnalité de tranche à Array. Je ne voulais pas copier leur ensemble de code car il est vraiment long, mais je ne voulais pas laisser un lien ici sans code non plus. – Nikki9696

+0

Très bien, merci! – Alex

0

modifié pour corriger erreur indiqué dans un commentaire

Cela pourrait résoudre votre problème:

function f() {alert("in f");} 
var saved_f = f; 
var f = function() { 
    alert("in f2"); 
    saved_f(); 
} 
f(); 
+0

'saved_f' pointera vers la dernière fonction définie' f' (provoquant une récursion infinie). Les déclarations de fonction font l'objet de [levage] (http://stackoverflow.com/questions/1710424/referencing-a-javascript-value-before-it-is-declared-can- some-explain-this/1710509#1710509). Cela peut sembler fonctionner si vous l'essayez sur la console du firebug, car les implémentations de Mozilla définissent une instruction Function, et le code évalué par la console est enveloppé dans un bloc 'with'. Dans fbug, essayez d'enrouler le code ci-dessus dans une fonction anonyme, par ex. '(function() {})();' – CMS

+0

@CMS Merci pour la correction et l'instruction. J'ai édité pour en tenir compte (et testé en dehors de firebug). –