在引用原始函数时覆盖 JavaScript 函数

IT技术 javascript overriding user-defined-functions
2021-02-06 01:10:06

我有一个函数,a(),我想覆盖它,但也有a()根据上下文按顺序执行的原始函数例如,有时当我生成一个页面时,我想像这样覆盖:

function a() {
    new_code();
    original_a();
}

有时像这样:

function a() {
    original_a();
    other_new_code();
}

我如何original_a()从覆盖范围内获得它a()甚至有可能吗?

请不要建议以这种方式替代覆盖,我知道很多。我是专门问这种方式的。

6个回答

你可以这样做:

var a = (function() {
    var original_a = a;

    if (condition) {
        return function() {
            new_code();
            original_a();
        }
    } else {
        return function() {
            original_a();
            other_new_code();
        }
    }
})();

original_a在匿名函数内部声明可以防止它弄乱全局命名空间,但它在内部函数中可用。

就像评论中提到的 Nerdmaster 一样,一定要()在最后加上 。您想调用外部函数并将结果(两个内部函数之一)a存储在,而不是将外部函数本身存储在 中a

对于像我这样的任何白痴 - 请密切注意最后的“()” - 否则,它将返回外部函数,而不是内部函数:)
2021-03-18 01:10:06
哇,我尝试在没有命名空间的情况下执行此操作,但堆栈溢出,大声笑。
2021-03-21 01:10:06
@MuhammadUmer 你是对的,函数表达式周围的括号不是必需的。我包含它们是因为没有它们,如果你只看前几行,它看起来(至少对我来说)就像你将外部函数直接分配给a,而不是调用它并存储返回值。括号让我知道还有其他事情发生。
2021-03-31 01:10:06
我认为如果从函数中删除第一个和最后一个括号,结果将是相同的。喜欢从这里(functi..})只是这样做}();会产生相同的结果,因为使用了(function{})()第一组括号,因为您不能只声明匿名函数表达式,您必须分配它。但是通过执行 () 你并没有定义任何只是返回一个函数的东西。
2021-04-01 01:10:06
@Nerdmaster 感谢您指出这一点。我添加了一个注释,希望能帮助人们注意到。
2021-04-05 01:10:06

代理模式可以帮助你:

(function() {
    // log all calls to setArray
    var proxied = jQuery.fn.setArray;
    jQuery.fn.setArray = function() {
        console.log( this, arguments );
        return proxied.apply( this, arguments );
    };
})();

以上将其代码包装在一个函数中以隐藏“代理”变量。它将 jQuery 的 setArray 方法保存在一个闭包中并覆盖它。然后代理记录对该方法的所有调用,并将调用委托给原始方法。使用 apply(this, arguments) 保证调用者不会注意到原始方法和代理方法之间的区别。

的确。'apply' 和 'arguments' 的使用使得这比其他答案更可靠
2021-03-25 01:10:06
请注意,此模式不需要 jQuery — 它们只是使用 jQuery 的一个函数作为示例。
2021-03-28 01:10:06

谢谢你们,代理模式真的很有帮助.....实际上我想调用一个全局函数 foo.. 在某些页面中我需要做一些检查。所以我做了以下事情。

//Saving the original func
var org_foo = window.foo;

//Assigning proxy fucnc
window.foo = function(args){
    //Performing checks
    if(checkCondition(args)){
        //Calling original funcs
        org_foo(args);
    }
};

Thnx 这真的帮助了我

当遵循代理模式时,在某些情况下实现此答案代码中不存在的此细节将很重要:而不是org_foo(args)调用org_foo.call(this, args). 这将保持this为 window.foo 正常调用(未代理)时的状态。看到这个答案
2021-03-30 01:10:06

您可以使用如下结构覆盖函数:

function override(f, g) {
    return function() {
        return g(f);
    };
}

例如:

 a = override(a, function(original_a) {
      if (condition) { new_code(); original_a(); }
      else { original_a(); other_new_code(); }
 });

编辑:修正了一个错字。

...但如果我没记错的话,这仅限于零参数函数,或者至少是一些预定数量的参数。有没有办法将其推广到任意数量的参数而不会失去可读性?
2021-03-14 01:10:06
@MuMind:是的,但正确使用代理模式 - 请参阅我的回答
2021-04-05 01:10:06
+1 这比其他代理模式示例更具可读性!
2021-04-08 01:10:06

传递任意参数:

a = override(a, function(original_a) {
    if (condition) { new_code(); original_a.apply(this, arguments) ; }
    else { original_a.apply(this, arguments); other_new_code(); }
});
不会争论original_a吗?
2021-03-14 01:10:06