2011-04-28 99 views
1

我有一个脚本,基于特定的场景,可能需要取代函数来在最终调用原始函数之前进行一些处理。 (请参阅“'overriding' Javascript Function”)动态替换不在全局范围内的函数

我一般可以得到这个工作 - 在这里是一个使用jQuery插件Tinyscrollbar(不是我预期的应用,只是一些快速和容易的说明)一个简单的例子:

(function ($) { 
    // Snip.. 

    function initalize() { 
     oSelf.update(); 
     setEvents(); 
     return oSelf; 
    } 

    // Snip.. 

    function setEvents() { 

     (function() { 
      var oldInit = wheel; 

      wheel = function (oEvent) { 
       console.log('Intercept'); 
       oldInit(oEvent); 
      } 
     })(); 

     // Original event code, irrelevant to question 
    } 

    function wheel(oEvent) { 
     // Actual function, related to using the mousewheel 
    } 

})(jQuery); 

当我滚动鼠标滚轮,控制台打印“拦截”,滚动条按原定义移动。精彩!

但是,函数名是硬编码的,并不在全局范围内,所以window []不可用(我喜欢)。是否有任何可能的黑魔法,'new Function()'和/或其他方式组合循环遍历潜在的函数名称列表(可能会根据其他逻辑进行更改)并将它们封装在这个(或类似的内部函数)精神)的态度?

在此先感谢!

回答

1

不幸的是,有没有办法一一列举或动态的范围对象访问成员(与全球范围/ window对象的便捷除外)

所以你需要修改你的代码位。而不是在你的外部函数中有自由浮动函数,而是在它们上面有方法的对象。这会使得更换这些方法变得更容易。

如果您在开始将它们分配为事件处理程序或其他类型之后修改函数,那么还有一些额外的技巧。如果你碰巧在这些函数中使用了某种bind()包装,你的行为的正确性将取决于bind()函数。

具体来说,如果您希望替换方法追溯地成为调用它的任何事件处理程序或回调的方法,您将需要使用一个bind()包装器,该包装器需要一个上下文对象和一个字符串是函数名称而不是上下文对象和函数引用。 (并确保bind()不会早期解析该字符串以便在每次调用时削减一些ms)。

如果不想要追溯行为,则仍然必须确保不要有一些bind() - 版本的原始方法漂浮在你的替换发生后仍然用于新的回调。

+0

够公平的,我非常感谢回应。对于它的价值,我的实际应用程序没有尝试取代bind() - s,所以至少很多疯狂不适用;但绝对值得指出。通过在init() - 时间引用的对象属性中编写覆盖函数,我能够实现我的目标;不是超级时尚的生成代码,但它完成了工作,因为没有太多人担心。 – Morgon 2011-04-29 01:59:39