在引用原文的同时覆盖JavaScript函数
我有一个函数, a()
,我想重写,但也有原始的a()
按顺序执行取决于上下文。 例如,有时当我生成一个页面,我想要这样重写:
function a() { new_code(); original_a(); }
有时候是这样的:
function a() { original_a(); other_new_code(); }
我如何从顶部的a()
获得original_a()
a()
? 这甚至有可能吗?
请不要以这种方式build议替代scheme,我知道很多。 我正在问这个具体的方式。
你可以做这样的事情:
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
。
代理模式可能会帮助您:
(function() { // log all calls to setArray var proxied = jQuery.fn.setArray; jQuery.fn.setArray = function() { console.log( this, arguments ); return proxied.apply( this, arguments ); }; })();
上面的代码包含在一个函数中以隐藏“代理”variables。 它将jQuery的setArray方法保存在闭包中并覆盖它。 代理然后logging对该方法的所有调用并将该调用委托给原始。 使用apply(this,arguments)可以保证调用者不会注意到原始代码和代理方法之间的区别。
感谢球员的代理模式真的帮助…..其实我想要调用一个全局函数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这真的帮了我
你可以使用如下构造来覆盖函数:
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(); } });
传递任意参数:
a = override(a, function(original_a) { if (condition) { new_code(); original_a.apply(this, arguments) ; } else { original_a.apply(this, arguments); other_new_code(); } });
上面的例子没有正确地应用this
或正确的传递arguments
给函数覆盖。 Underscore _. wrap()包装现有的函数,应用this
并正确地传递arguments
。 请参阅: http : //underscorejs.org/#wrap
我有一些别人编写的代码,并希望添加一个函数,我无法在代码中find。 所以作为一个解决方法,我想重写它。
没有解决scheme为我工作。
这是什么在我的情况下工作:
if (typeof originalFunction === "undefined") { originalFunction = targetFunction; targetFunction = function(x, y) { //Your code originalFunction(a, b); //Your Code }; }
我为类似的场景创build了一个小帮手,因为我经常需要重写几个库的函数。 这个助手接受一个“命名空间”(函数容器),函数名和覆盖函数。 它将用新的名称空间replace引用的名称空间中的原始函数。
新函数接受原始函数作为第一个参数,原始函数参数作为其余部分。 每次都会保存上下文。 它支持void和non-void函数。
function overrideFunction(namespace, baseFuncName, func) { var originalFn = namespace[baseFuncName]; namespace[baseFuncName] = function () { return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0))); }; }
用例如Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) { // ... do stuff before base call baseFn(obj); // ... do stuff after base call });
我没有创build任何性能testing。 它可能会添加一些不必要的开销,这可能或不是一个大问题,取决于情况。
在我看来,最重要的答案是不可读/可维护的,其他答案没有正确地绑定上下文。 这是一个使用ES6语法解决这两个问题的可读解决scheme。
const orginial = someObject.foo; someObject.foo = function() { if (condition) orginial.bind(this)(...arguments); };
@Matthew Crumley提供的答案是利用立即调用的函数expression式,将旧的'a'函数closures到返回函数的执行上下文中。 我认为这是最好的答案,但个人而言,我更愿意把函数“a”作为parameter passing给IIFE。 我觉得这是可以理解的。
var a = (function(original_a) { if (condition) { return function() { new_code(); original_a(); } } else { return function() { original_a(); other_new_code(); } } })(a);