Javascript:扩展function

我想要的主要原因是我想扩展我的初始化函数。

像这样的东西:

// main.js window.onload = init(); function init(){ doSomething(); } // extend.js function extends init(){ doSomethingHereToo(); } 

所以我想扩展一个function,比如我在PHP中扩展一个类。

我想从其他文件扩展它,所以例如我有main.js的原始init函数和extended.js中的扩展函数。

从更广泛的angular度来看,你实际上正在做什么以及你正在做什么的背景下,我相信我们可以给你一个比你的问题字面答案更好的答案。

但是这里是一个字面的答案:

如果您将这些函数分配给某个属性,您可以将原始函数包装起来,并将其replace为属性:

 // Original code in main.js var theProperty = init; function init(){ doSomething(); } // Extending it by replacing and wrapping, in extended.js theProperty = (function(old) { function extendsInit() { old(); doSomething(); } return extendsInit; })(theProperty); 

如果你的函数不在一个对象上,你可能想把它们放在那里,以方便上述。 例如:

 // In main.js var MyLibrary = (function() { var publicSymbols = {}; publicSymbols.init = init; function init() { } return publicSymbols; })(); // In extended.js (function() { var oldInit = MyLibrary.init; MyLibrary.init = extendedInit; function extendedInit() { oldInit.apply(MyLibrary); // Use #apply in case `init` uses `this` doSomething(); } })(); 

但是有更好的方法可以做到这一点。 例如,提供注册init函数的方法。

 // In main.js var MyLibrary = (function() { var publicSymbols = {}, initfunctions = []; publicSymbols.init = init; function init() { var funcs = initFunctions; initFunctions = undefined; for (index = 0; index < funcs.length; ++index) { try { funcs[index](); } catch (e) { } } } publicSymbols.addInitFunction = addInitFunction; function addInitFunction(f) { if (initFunctions) { // Init hasn't run yet, rememeber it initFunctions.push(f); } else { // `init` has already run, call it almost immediately // but *asynchronously* (so the caller never sees the // call synchronously) setTimeout(f, 0); } } return publicSymbols; })(); 

(上面的大部分内容可以写得更简洁一点,但是我想使用publicSymbols这样的明确名称,而不是我通常的pubs或者匿名对象字面值,如果你想要匿名函数,可以写得更紧凑一点,但是我不要太在乎匿名function 。)

有几种方法可以解决这个问题,这取决于你的目的是什么,如果你只是想执行这个函数,并且在同一个上下文中,你可以使用.apply()

 function init(){ doSomething(); } function myFunc(){ init.apply(this, arguments); doSomethingHereToo(); } 

如果你想用一个更新的init来replace它,它会看起来像这样:

 function init(){ doSomething(); } //anytime later var old_init = init; init = function() { old_init.apply(this, arguments); doSomethingHereToo(); }; 

其他的方法很好,但是它们不保存任何附加到init的原型函数。 为了解决这个问题,你可以做以下的事情(来自Nick Craver的文章)。

 (function () { var old_prototype = init.prototype; var old_init = init; init = function () { old_init.apply(this, arguments); // Do something extra }; init.prototype = old_prototype; }) (); 

另一种select可能是:

 var initial = function() { console.log( 'initial function!' ); } var iWantToExecuteThisOneToo = function () { console.log( 'the other function that i wanted to execute!' ); } function extendFunction( oldOne, newOne ) { return (function() { oldOne(); newOne(); })(); } var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo ); 

使用extendFunction.js

 init = extendFunction(init, function(args) { doSomethingHereToo(); }); 

但在您的具体情况下,扩展全局onload函数会更容易:

 extendFunction('onload', function(args) { doSomethingHereToo(); }); 

其实我真的很喜欢你的问题,这让我想到不同的用例。

对于JavaScript事件,你真的想添加和删除处理程序 – 但对于extendFunction,你以后如何删除function? 我可以很容易地将.revert方法添加到扩展函数,所以init = init.revert()将返回原始函数。 显然这可能会导致一些非常糟糕的代码,但也许它可以让你做一些事情,而无需触及代码库的外部部分。