2013-07-28 69 views
1

假設我想包裝一個任意函數來添加類似日誌記錄(或其他任何東西)。包裝應該是通用的,並且可以用任何類型的參數調用任何f如何在包裝另一個函數的coffeescript中編寫函數?

createWrapper= (f) -> 
    wrapper= -> 
    # do the logging or whatever I want before I call the original 
    result= ??? 
    # do whatever after the original function call 
    result 

用法是:

g=createWrapper(f) 

現在g應該以任何方式f會被稱爲叫,像

result = g(1,2,3) 

應返回相同的

result = f(1,2,3) 

A現在我可以使用g無論我使用f但它調用我的包裝函數。

我的問題是:我應該如何撥打f得到結果?

+1

我的猜測是:'''f.apply @,arguments''' –

+0

你的猜測是正確的:)。這是一個很好的閱讀JS裝飾器功能(將其翻譯爲CS應該沒有問題):https://github.com/raganwald/homoiconic/blob/master/2013/01/function_and_method_decorators.md – epidemian

回答

2

答案是

f.apply @, arguments 

因此,包裝看起來像

createWrapper= (f) -> 
    -> 
    # do the logging or whatever I want before I call the original 
    result= f.apply @, arguments 
    # do whatever after the original function call 
    result 

,或者如果您不希望以後做任何事致電

createWrapper= (f) -> 
    -> 
    # do the logging or whatever I want before I call the original 
    f.apply @, arguments 

或者如果您想更清楚些,可以使用splat。 這有一個優點,即參數是一個列表,您可以對參數應用 列表操作。

createWrapper= (f) -> 
    (args...) -> 
    # do the logging or whatever I want before I call the original 
    result= f.apply @, args 
    # do whatever after the original function call 
    result 

下面是一些測試code

createWrapper= (f) -> 
    (args...) -> 
    # do the logging or whatever I want before I call the original 
    result= f.apply @, args 
    # do whatever after the original function call 
    result 

class cl 
    i: 10 
    f: (x) -> 
    x + @i 
    getf: (x) -> 
    (x)=>@f(x) 

c =new cl 
f1 = c.getf() 
g1 = createWrapper(f1) 
if f1(1)!=g1(1) 
    throw new Error("failed f1 #{f1 1} != #{g1 1}") 

f2 = (x) -> x+20 
g2 = createWrapper(f2) 
if f2(1)!=g2(1) 
    throw new Error("failed f2 #{f2 1} != #{g2 1}") 


f3 = (args...) -> "#{args}" 
g3 = createWrapper(f3) 
if f3(1,2,3)!=g3(1,2,3) 
    throw new Error("failed f3 #{f3 1,2,3} != #{g3 1,2,3}") 

f4 = -> arguments[0] 
g4 = createWrapper(f4) 
if f4(1)!=g4(1) 
    throw new Error("failed f4 #{f4 1} != #{g4 1}") 

f5 = c.f 
g5 = createWrapper(f5) 
if f5.apply(c,[1])!=g5.apply(c,[1]) 
    throw new Error("failed f5 #{f5.apply c,[1]} 1= #{g5.apply c,[1]}") 

alert(""" 
Everything is OK: 
    f1 #{f1 1} == #{g1 1} 
    f2 #{f2 1} == #{g2 1} 
    f3 #{f3 1,2,3} == #{g3 1,2,3} 
    f4 #{f4 1} == #{g4 1} 
    f5 #{f5.apply c,[1]} == #{g5.apply c,[1]} 
""") 
0

只要運行F()

createWrapper = (f) -> 
    wrapper= -> 
    # do the logging or whatever I want before I call the original 
    result= f() 
    # do whatever after the original function call 
    result 
+0

我想要的參數是傳遞到f - 我應該讓我的問題更清楚了...... –

相關問題