2009-01-08 44 views
2

我有一個javascript函數(類),需要一個函數引用作爲一個參數。擴展Javascript功能作爲參數傳遞

function MyClass (callBack) { 
    if (typeof callBack !== 'function') 
    throw "You didn't pass me a function!" 
} 

的原因,我不會到這裏,我需要在一個匿名函數封閉它追加東西的功能,但唯一的辦法我已經能夠找出如何做到這一點是通過將公共函數添加到MyClass,它將callBack函數作爲參數並返回修改後的版本。

function MyClass() { 
    this.modifyCallBack = function (callBack) { 
     var oldCallBack = callBack; 
     callBack = function() { 
      oldCallBack(); // call the original functionality 
      /* new code goes here */ 
     } 
     return callBack; 
    } 
} 

/* elsewhere on the page, after the class is instantiated and the callback function defined */ 
myCallBackFunction = MyClassInstance.modifyCallBack(myCallBackFunction); 

當將callBack函數作爲參數傳遞給類時,可以使此工作成爲可能嗎?嘗試以這種方式修改函數時,將它作爲參數進行passign似乎只會影響它在類中的實例,但這似乎不是一個有效的假設,因爲函數是javascript中的對象,因此被傳遞參考。

更新:作爲crescentfresh指出(我沒有解釋得很好),我想修改callBack函數就地。如果有可能在類實例化時執行所有這些操作,我寧願不調用第二個函數。

回答

5

函數對象不提供方法來修改它們。因此,你想要做的事情不可能像你想做的那樣。 Jon Skeet喜歡指出Java的作用是一樣的:對象不是通過引用傳遞的,而是一個指向它們的指針是通過值傳遞的。這意味着將參數變量的值更改爲新參數並不會影響原始參數。

只有兩種方法可以在按值調用的語言(如Java和JavaScript)中執行所需操作:第一種方法是使用(函數)對象的方法對其進行修改。正如我已經說過的,函數對象沒有這些。另一個是將函數對象的屬性作爲第二個參數傳遞給對象,並將相應的屬性設置爲包裝舊函數的新函數。

實施例:

var foo = {}; 
foo.func = function() {}; 

function wrapFunc(obj) { 
    var oldFunc = obj.func; 
    obj.func = function() { 
     // do some stuff 
     oldFunc.call(obj, _some_argument__); 
    }; 
} 

wrapFunc(foo); 

這適用於全局功能,以及:它們是window對象的屬性。

0

我假設你保存這個回調的地方...任何理由,這將無法正常工作?

function MyClass (callBack) { 
    var myCallBack; 

    if (typeof callBack !== 'function') 
    throw "You didn't pass me a function!" 

    var oldCallBack = callBack; 
    callBack = function() { 
    oldCallBack(); // call the original functionality 
    /* new code goes here */ 
    } 
    myCallBack = callback; 
} 
+0

因爲回調是引用傳遞,不應該分配匿名函數將其更改它在全局命名空間(它從哪裏傳遞)?將它分配給myCallBack將在該類中創建一個新的引用,但是新代碼永遠不會運行,這使我在某處出錯 – dmercer 2009-01-08 19:10:09

+0

dmercer,您想修改callBack * in place *?因此,在將它傳遞給你的類之後,調用者可以調用它,但讓它運行一些額外的代碼? – 2009-01-08 19:16:39

0

你想要做的事,如:

function MyClass() { 
    this.modifyCallBack = function (callBack) { 
     var oldCallBack = callBack; 
     callBack = function() { 
      oldCallBack(); // call the original functionality 
      alert("new functionality"); 
     } 
     return callBack; 
    } 
} 

/* elsewhere on the page, after the class is instantiated and the callback function defined */ 
var myCallBackFunction = function() {alert("original");}; 
var MyClassInstance = new MyClass(); 
myCallBackFunction = MyClassInstance.modifyCallBack(myCallBackFunction); 
myCallBackFunction(); 
1

如JavaScript下列變量使用詞彙範圍是可能的:

var modifiableCallback=function() { alert('A'); }; 


function ModifyCallbackClass(callback) 
{ 
    modifiableCallback=function() { callback(); alert('B'); }; 
} 


function body_onload() 
{ 

    var myClass=new ModifyCallbackClass(modifiableCallback); 

    modifiableCallback(); 

} 

這你想要做什麼,但功能「modifiableCallback」必須與內ModifyCallbackClass相同的名稱被引用,否則會被關閉不適用。所以這可能會限制這種方法對你有用。

使用eval(性能可能會受些影響),也可能使這種方法更加靈活:

var modfiableCallback1=function() { alert('A'); }; 

var modfiableCallback2=function() { alert('B'); }; 

var modfiableCallback3=function() { alert('C'); }; 

function ModifyCallbackClass(callbackName) 
{ 
    var temp=eval(callbackName); 
    var temp2=eval(callbackName); 

    temp= function() { temp2(); alert('Modified'); }; 

    eval(callbackName + " = temp;"); 
} 


function body_onload() 
{ 

    var myClass=new ModifyCallbackClass("modfiableCallback1"); 

    modfiableCallback1(); 

    myClass=new ModifyCallbackClass("modfiableCallback2"); 

    modfiableCallback2(); 

    myClass=new ModifyCallbackClass("modfiableCallback3"); 

    modfiableCallback3(); 

}