Hooks de fonctions Javascript

EDIT: OK, je crois que les solutions suivantes sont valides:

  1. Utilisez le plugin jQuery AOP. Il enveloppe fondamentalement l'ancienne fonction avec le crochet dans un sandwich de fonction et la réassigne à l'ancien nom de fonction. Cela provoque l'imbrication de fonctions avec chaque nouveau crochet.

    Si jQuery n'est pas utilisable pour vous, pillez simplement le code source, il ne semble pas y avoir de dépendances jQuery dans le plugin, et la source est simple et très petit.

  2. avoir un objet décrivant tous les crochets et leurs cibles et un pour stocker la fonction initiale non modifiée. Lors de l'ajout d'un nouveau crochet, l'enrubannage serait refait autour de la fonction d'origine, au lieu de Ré-enrouler la fonction d'enrubannage précédente.

    Vous échappez aux fonctions imbriquées, et obtenez deux objets à manipuler à la place. Potentiellement, cela pourrait aussi signifier une manipulation plus facile de crochet, si vous ajoutez / retirez des crochets souvent et hors de ordre.

je vais choisir le premier, puisque c'est déjà fait, et je n'ai pas de performance à m'inquiéter. Et puisque les fonctions d'origine ne sont pas affectées, même si je change les méthodes d'accrochage, je vais seulement avoir besoin de refaire l'ajout de crochet, qui pourrait être juste quelques opérations simples de recherche et de remplacement.


Salut,

est-il possible de créer un mécanisme, dans lequel la fonction a pourrait avoir un ensemble de crochets(fonctions qui s'exécuteront avant / après la fonction)?

idéalement, la fonction A ne serait pas au courant de la fonctionnalité d'accrochage, de sorte que je n'ai pas à modifier le code source de la fonction a pour appeler les crochets. Quelque chose comme:

A = function(){
    alert("I'm a naive function");
};
B = function(){
    alert("I'm having a piggyback ride on function A!"+
          "And the fool doesn't even know it!");
};
addHook(B, A)//add hook B to function A
A()
//getting alerts "I'm a naive function"/"I'm having a 
//piggyback ride on function A! And the fool doesn't even know it!"

j'ai essayé de pirater quelque chose pour un couple d'heures, mais jusqu'à présent aucune chance.

12
demandé sur Seyen 2009-04-26 00:04:22

7 réponses

regardez le plugin AOP de jQuery. En général, google "programmation axée sur l'aspect javascript".

10
répondu Travis Jensen 2009-04-25 20:13:44

Peut-être pas assez, mais il semble fonctionner...

<script>

function A(x) { alert(x); return x; }
function B() { alert(123); }

function addHook(functionB, functionA, parent)
{
    if (typeof parent == 'undefined')
        parent = window;

    for (var i in parent)
    {
        if (parent[i] === functionA)
        {
            parent[i] = function()
            {
                functionB();
                return functionA.apply(this, arguments)
            }

            break;
        }
    }
}

addHook(B, A);

A(2);

</script>
12
répondu Greg 2009-04-25 20:17:53

réponse Très simple:

function someFunction() { alert("Bar!") }
var placeholder=someFunction;
someFunction=function() {
  alert("Foo?");
  placeholder();
}
3
répondu Asmor 2010-10-18 18:05:32

Cette réponse n'est pas définitive, mais plutôt de démonstration d'une technique différente que ceux proposés jusqu'à présent. Cela tient compte du fait qu'une fonction en Javascript est un objet de première classe, et en tant que tel, a) vous pouvez la passer comme valeur à une autre fonction et b) vous pouvez y ajouter des propriétés. Combinez ces caractéristiques avec les méthodes "call" (ou "apply") intégrées à la fonction, et vous avez vous-même un début vers une solution.

var function_itself = function() {
    alert('in function itself');
}
function_itself.PRE_PROCESS = function() {
    alert('in pre_process');
}
function_itself.POST_PROCESS = function() {
    alert('in post_process');
}

var function_processor = function(func) {
    if (func.PRE_PROCESS) {
        func.PRE_PROCESS.call();
    }
    func.call();
    if (func.POST_PROCESS) {
        func.POST_PROCESS.call();
    }        
}
2
répondu George Jempty 2009-04-25 21:11:42

La fonction suivante vous donnera avant et après les crochets qui peuvent être empilés. Donc, si vous avez un certain nombre de fonctions qui ont besoin de courir avant la fonction donnée ou après la fonction donnée alors ce serait une solution de travail. Cette solution ne nécessite pas de jQuery et utilise des méthodes natives array (pas de shims requis). Il devrait aussi être sensible au contexte donc si vous appelez la fonction originale avec un contexte Si devrait exécuter chaque fonction avant et après pareillement.

// usage: 
/*
function test(x) {
    alert(x);
}

var htest = hookable(test);

htest.addHook("before", function (x) {
    alert("Before " + x);
})
htest.addHook("after", function (x) {
    alert("After " + x);
})

htest("test") // => Before test ... test ... After test
*/
function hookable(fn) {
    var ifn = fn,
        hooks = {
            before : [],
            after : []
        };

    function hookableFunction() {
        var args = [].slice.call(arguments, 0),
            i = 0,
            fn;
        for (i = 0; !!hooks.before[i]; i += 1) {
            fn = hooks.before[i];
            fn.apply(this, args);
        }
        ifn.apply(this, arguments);
        for (i = 0; !!hooks.after[i]; i++) {
            fn = hooks.after[i];
            fn.apply(this, args);
        }
    }

    hookableFunction.addHook = function (type, fn) {
        if (hooks[type] instanceof Array) {
            hooks[type].push(fn);
        } else {
            throw (function () {
                var e = new Error("Invalid hook type");
                e.expected = Object.keys(hooks);
                e.got = type;
                return e;
            }());
        }
    };

    return hookableFunction;
}
1
répondu Gabriel 2011-09-27 05:26:29

Voici ce que j'ai fait, pourrait être utile dans d'autres applications comme ceci:

//Setup a hooking object
a={
    hook:function(name,f){
        aion.hooks[name]=f;
    }
}a.hooks={
    //default hooks (also sets the object)
}; 

//Add a hook
a.hook('test',function(){
    alert('test');
});

//Apply each Hook (can be done with for)
$.each(a.hooks,function(index,f){
    f();
});
0
répondu aubreypwd 2013-04-23 20:52:33

je ne sais pas si ce sera utile. Vous avez besoin de modifier la fonction originale mais seulement une fois et vous n'avez pas besoin de continuer à l'éditer pour tirer des crochets

https://github.com/rcorp/hooker

0
répondu Gaurav Ramanan 2015-01-01 17:14:33