2010-10-27 80 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