2010-10-27 45 views
1

所以,我想每次调用某个函数都要执行一些代码,这是可行的吗?事情是,我可以覆盖现有的函数并添加代码,但这需要我知道该函数的确切内容......想象一下“库”的“插件”,并且想要插件,在每次执行代码时都会调用这个图书馆的特定功能,但是你不想覆盖原来的图书馆内容......希望我已经清楚了!Javascript:如何在函数调用中执行代码而不覆盖该函数?

如果它是可行的,有没有办法检索提交给函数的参数?

+0

在[面向方面](http://en.wikipedia.org/wiki/Aspect-oriented_programming)和[功能](http://en.wikipedia.org/wiki/Functional_programming)编程,你问的是[[建议]](http://en.wikipedia.org/wiki/Advice_%28programming%29)。 – outis 2010-10-28 00:06:05

回答

1

这绝对是可行的。 JS是一种动态语言,因此您可以使用自己的函数交换存储在对象中的函数。例如:

var fxnToWrap = obj.someFunction; 
obj.someFunction = function() { 
    console.log("booyah, I'm intercepting every call to obj.someFunction"); 
    fxnToWrap.apply(obj, arguments); 
} 
+0

这就是我一直在寻找的!不知道.apply(),似乎对我非常有用,谢谢! – Alex 2010-10-27 21:01:04

+0

我很确定倒数第二行应该是fxnToWrap.apply(obj,arguments);因为要应用的第一个参数设置函数运行的上下文(即将分配给它的内容)。通过将其设置为obj,func将能够使用它来访问该对象的属性和方法。 – 2010-10-27 23:43:28

+0

@Sid_M你是对的!固定。 – kevingessner 2010-10-28 01:25:25

1

可能你可以覆盖对函数的引用?例如:

function add1(x) { return x + 1; } 
function log_calls(f, name) { 
    return function() { 
     console.log("got a call to", name, "with args", arguments); 
     return f.apply(null, arguments); 
    } 
} 
add1 = log_calls(add1, "add1"); 

然后调用add1会是这样的:

>> x = add1(42) 
"got call to add1 with args [42]" 
>> x 
43 
+0

请问我需要什么,谢谢。 – Alex 2010-10-27 21:01:56

3

听起来像一个工作,一个包装函数给我。

编写一个调用其他函数的函数,并将你的代码放在那个(或任何地方)的末尾。然后总是调用你的版本。

适配器模式的排序。 http://en.wikipedia.org/wiki/Adapter_pattern

我相信你可以隐藏原始函数的作用域,并且如果你不能修改调用代码(不适用于像alert这样的一些内在函数,但应该适用于库代码),那么你的名字也是一样的。如果这不是一个选项,请参阅原型是否允许您扩展对象以添加功能。 http://phrogz.net/js/classes/ExtendingJavaScriptObjectsAndClasses.html

//Only add this implementation if one does not already exist. 
if (Array.prototype.slice==null) Array.prototype.slice=function(start,end){ 
    if (start<0) start=this.length+start; //'this' refers to the object to which the prototype is applied 
    if (end==null) end=this.length; 
    else if (end<0) end=this.length+end; 
    var newArray=[]; 
    for (var ct=0,i=start;i<end;i++) newArray[ct++]=this[i]; 
    return newArray; 
} 

对于参数,你也可以让你的版本采取可选的参数(类似的jQuery/MooTools的),然后看看发生了什么过去了。

此处可选参数的示例。 http://www.openjs.com/articles/optional_function_arguments.php

function accident() { 
    for(var i = 0; i < arguments.length; i++) { 
     alert("This accident was caused by " + arguments[i]); 
    } 
} 
+0

感谢您的回答!我会读一读这些内容,但是在帖子末尾的参数非常有用,以前从未使用过;)。我没有得到数组的东西与我的probelm必须做什么?只是关于如何使用原型的“演示”? – Alex 2010-10-27 21:13:58

+0

是的,它是从我作为原型演示的一部分贴在它上面的链接复制的;他们正在向Array添加切片功能。我不想复制他们的整套代码,因为它很长,但我不想在这里留下一个没有代码的链接。 – Nikki9696 2010-10-27 22:16:18

+0

好的,谢谢! – Alex 2010-10-28 10:47:33

0

编辑以纠正错误的评论

指出,这可能会解决你的问题:

function f() {alert("in f");} 
var saved_f = f; 
var f = function() { 
    alert("in f2"); 
    saved_f(); 
} 
f(); 
+0

'saved_f'将指向最后一个'f'定义的函数(导致无限递归)。函数声明是[提升]的主题(http://stackoverflow.com/questions/1710424/referencing-a-javascript-value-before-it-is-declared-can-someone-explain-this/1710509#1710509)。如果你在Firebug的控制台上尝试它,似乎可以工作,因为Mozilla实现定义了一个Function语句,并且控制台评估的代码被封装在一个'with'块中。在fbug中,尝试使用匿名函数来封装上述代码,例如'(function(){})();' – CMS 2010-10-27 20:47:57

+0

@CMS感谢您的纠正和指导。我已经编辑了这个考虑(并在萤火虫外测试)。 – 2010-10-27 23:52:31