14

编辑:好的,我相信以下解决方案是有效的:

  1. 使用 jQuery AOP 插件。它基本上将旧函数与钩子一起包装成一个函数三明治,并将其重新分配给旧函数名。这会导致每个新添加的钩子都嵌套函数。
    如果 jQuery 不适合你,那就盗版源码吧,插件里面好像没有 jQuery 依赖,而且源码简单而且很小。

  2. 有一个描述所有钩子及其目标的对象和一个用于存储初始未修改函数的对象。添加新钩子时,将围绕原始函数重做包装,而不是重新包装先前的包装函数。
    您转义嵌套函数,并获取两个对象来处理。如果您经常无序地添加/删除钩子,这也可能意味着更容易处理钩子。

我会选择第一个,因为它已经完成了,我不用担心性能。并且由于原有功能不受影响,即使我切换钩子方法,我只需要重新添加钩子,这可能只是一些简单的搜索和替换操作。


你好,

是否有可能创建一种机制,其中函数 A 可能有一组钩子(将在函数 A 之前/之后执行的函数)?

理想情况下,函数 A 不会意识到挂钩功能,因此我不必修改函数 A 的源代码来调用挂钩。就像是:

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!"

几个小时以来,我一直在尝试破解某些东西,但到目前为止还没有运气。

4

7 回答 7

13

可能不漂亮,但它似乎工作......

<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>
于 2009-04-25T20:17:53.230 回答
10

看看jQuery 的 AOP 插件。一般来说,谷歌“面向javascript方面的编程”。

于 2009-04-25T20:13:44.083 回答
4

非常简单的答案:

function someFunction() { alert("Bar!") }
var placeholder=someFunction;
someFunction=function() {
  alert("Foo?");
  placeholder();
}
于 2010-10-18T18:05:32.350 回答
2

这个答案不是确定的,而是说明了一种与迄今为止提供的不同的技术。这利用了 Javascript 中的函数是一等对象这一事实,因此,a)您可以将其作为值传递给另一个函数,并且 b)您可以向其添加属性。将这些特征与函数的内置“调用”(或“应用”)方法结合起来,您就有了一个解决方案的开始。

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();
    }        
}
于 2009-04-25T21:05:30.357 回答
1

以下函数将为您提供可以堆叠的前后挂钩。因此,如果您有许多潜在的函数需要在给定函数之前或给定函数之后运行,那么这将是一个可行的解决方案。此解决方案不需要 jQuery 并使用本机数组方法(不需要 shims)。它也应该是上下文敏感的,因此如果您使用上下文调用原始函数,是否应该同样运行每个函数之前和之后的函数。

// 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;
}
于 2011-09-27T05:26:29.837 回答
0

这就是我所做的,可能在像这样的其他应用程序中很有用:

//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();
});
于 2013-04-23T20:52:33.563 回答
0

我不知道这是否有用。您确实需要修改原始函数,但只需要修改一次,并且您不需要继续编辑它来触发钩子

https://github.com/rcorp/hooker

于 2015-01-01T17:14:33.717 回答