在引用原始函数时覆盖JavaScript函数
-
08-07-2019 - |
题
我有一个函数,a()
,我想要覆盖,但也可以根据上下文按顺序执行原始original_a()
。例如,有时当我生成一个页面时,我会想要覆盖这样:
function a() {
new_code();
original_a();
}
有时也喜欢这样:
function a() {
original_a();
other_new_code();
}
如何从超越<=>中获取<=>?它甚至可能吗?
请不要以这种方式建议替代方法,我知道很多。我是专门问这个问题的。
解决方案
你可以这样做:
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
中,而不是将外部函数本身存储在<=>中。
其他提示
代理模式可能会对您有所帮助:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
上面将其代码包装在函数中以隐藏<!> quot; proxied <!> quot; -variable。它将jQuery的setArray方法保存在一个闭包中并覆盖它。然后,代理会记录对方法的所有调用,并将调用委托给原始调用。使用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
到函数覆盖。下划线_.wrap()包装现有函数,应用<=>并正确传递<=>。请参阅: http://underscorejs.org/#wrap
@Matthew Crumley提供的答案是利用立即调用的函数表达式,将旧的“a”函数关闭到返回函数的执行上下文中。我认为这是最好的答案,但就个人而言,我更希望将函数'a'作为IIFE的参数传递。我认为这更容易理解。
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
我有一些其他人编写的代码,想要在代码中找不到的函数中添加一行代码。因此,作为一种解决方法,我想覆盖它。
虽然这些解决方案都不适用于我。
以下是我的案例:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}
我为类似的场景创建了一个小助手,因为我经常需要覆盖几个库中的函数。该助手接受<!> quot; namespace <!>; (函数容器),函数名称和重写函数。它将使用新的命名空间替换引用的命名空间中的原始函数。
新函数接受原始函数作为第一个参数,原始函数接受其余作用。它将每次保留上下文。它也支持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
});
我没有创建任何性能测试。它可能会增加一些不必要的开销,这可能是也可能不是很大,取决于场景。
在我看来,最常见的答案是不可读/可维护的,其他答案没有正确绑定上下文。这是一个使用ES6语法解决这两个问题的可读解决方案。
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
所以我的答案最终成为一个允许我使用指向原始对象的_this变量的解决方案。 我创建了一个<!>“Square <!>”的新实例;但是我讨厌<!>“Square <!>”的方式。生成它的大小。我认为应该遵循我的具体需求。但是为了做到这一点,我需要广场来更新<!>“GetSize <!>”;函数与该函数的内部函数调用广场中已存在的其他函数,例如this.height,this.GetVolume()。但为了做到这一点,我需要做到这一点,没有任何疯狂的黑客。所以这是我的解决方案。
其他一些Object初始化器或辅助函数。
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
另一个对象的功能。
updateToolbarButtons = function(viewer) {
var _viewer = viewer;
return function(width, height){
blah blah black sheep I can refer to this.anything();
}
};