我想要一种为预先存在的函数添加功能的方法,所以我做了这个:
Function.prototype.attachFunction = function(toAttach)
{
var func = this; //This is the original function, which I want to attack toAttach function to.
//Can I do this without wrapping it in a self-executing function? What's the difference?
func = (function()
{
return function()
{
func();
toAttach();
}
})();
return func; //Return the newly made function, not really important.
}
我将其粘贴到Google Chrome控制台中,并且没有任何错误,但是,根本不会改变原始功能。
f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f(); //Prints out just "g".
答案 0 :(得分:1)
您在attachFunction
原型上设置的Function
方法是一个高阶函数或组合器,它接受一个函数并返回一个新函数。正如预期的那样,它由之后创建的任何函数继承。但是,当它被调用时,它不会以任何方式改变f
的状态,它只会产生一个调用f
或调用函数的新函数。
所以,如果你想看到两个console.log
消息,你只需要调用它返回的函数,如下所示:
f.attachFunction(function(){console.log("hi")})();
或者更简单:
f.attachFunction(f)();
请注意,虽然函数是对象,但f
的执行上下文(代码)不是f
的属性,因此可以直接操作它,它保存在内部属性中。
答案 1 :(得分:1)
执行attachFunction
时,会返回执行func()
和toAttach
的函数。但是,如果您将代码更改为以下代码,它将尝试执行这两个函数,其中当前仍旧调用旧函数。
f = function() {console.log("g");};
f = f.attachFunction(function(){console.log("New function!");});
f(); //Causes an infinite loop since calling func() is the same as calling this()
要合并两个函数,我们需要以相同的方式包装它们,但不能在扩展Function
时包装它们var func1 = function(){
console.log('g');
};
var func2 = function(){
console.log('New function!');
};
func1 = (function(f1,f2){
return function(){
f1();
f2();
}
}(func1, func2));
func1(); //Writes out both g and New function!
我传入func1和func2作为参数的原因是为了防止进入无限循环的同样问题。我希望在那个时间点保持对这些功能的引用。
辅助函数将是以下
function combineFunctions(f1, f2){
return function(){
f1();
f2();
}
}
并将像这样使用
var f = function() {console.log("g");};
f = combineFunctions(f,function(){console.log("New function!");});
f();
答案 2 :(得分:0)
Underscore.js'wrap() function应该非常接近你想要的。
答案 3 :(得分:0)
目前,您正在尝试将变量调用为一个函数(toAttach
是一个变量,并且您在它的远端打了一些括号)。考虑一下:toAttach
可能包含一个函数,但这并不能使它成为一个函数(很像杂货店不是苹果)。相反,您需要调用变量中包含的函数。
有几种方法可以做到这一点(尽管这里只有一两个方法适用),[右]方式都不涉及eval()
(生活课程)。
考虑this线程。将函数名称作为字符串传递,然后使用
window[toAttach]();
调用该函数。它有点hacky,缺乏将函数作为对象传递的技巧,但它确实有效。
或者(完全取决于您的需要)您可以将函数绑定到事件。如果你是偷偷摸摸的(为什么不呢?)你可以使用
setTimeout(toAttach, 0);
其中toAttach
是对实际功能的引用(再次)。
最后,我认为最好是Function.call()方法。使用此方法,您可以调用填充在变量中的函数,甚至可以为this
传递上下文。
toAttach.call([Context]);
其中[Context]
是函数的上下文(即函数内部this
引用的内容,在大多数情况下,它可以留空以获得所需的范围)。我不能说我已经在你的某些情况下对它进行了测试(因此我最后将其包括在内),但我相信它应该会给你你正在寻找的结果。
答案 4 :(得分:0)
这是我实现这一目标的尝试,它并不干净,好像它完全在原型中但是它有效。可能比我的方法更好。
var bindings={};
function execBindings(func_name) {
if (bindings[func_name] != undefined) {
for (var i=0;i<bindings[func_name].length;i++) {
bindings[func_name][i]();
}
}
}
Function.prototype.bind=function(action){
if (bindings[this.name] == undefined) {
bindings[this.name]=[];
}
bindings[this.name].push(action);
}
然后,使用绑定:
function f() {
alert("foo");
execBindings("f");
}
f.bind(function(){
alert("bar");
});
f.bind(function(){
alert("test");
});
f();
导致3个警报,按照顺序绑定到该功能。
答案 5 :(得分:0)
我刚发现有两个问题。
f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f();
它肯定不起作用,导致attachFunction
只是环绕原始函数并返回包装,它不会改变原始函数,这意味着你的f
函数仍然是{{1 }}
如果您使用f = function() {console.log("g");}
的结果重新分配f
,则会出现attachFunction
。在Maximum call stack size exceeded
:
attachFunction
func = (function()
{
return function()
{
func();
toAttach();
}
})();
return func;
函数递归调用自己。
我更喜欢这种方法。
func