2014-11-09 58 views
0

我試圖創建一個函數,該函數可以創建一個圍繞對象方法的「代理」。這個「代理」將用於處理Web請求,然後調用目標方法。代理功能類似於這樣:動態引用函數時的Javascript變量範圍

var proxy = function(c) { 
    var proxy = {}; 
    for(var member in c) { 
    var args = c[member].toString().match (/function\s*\w*\s*\((.*?)\)/)[1].split (/\s*,\s*/); 
    proxy[member] = function(params) { 
     var methodArgs = args.map(function(argName) { 
     return params[argName]; 
     }); 
     return c[member].apply(c, methodArgs); 
    } 
    } 
    return proxy; 
}; 

所以,如果我有這樣的原始控制器,

var c = { 
    sum: function(x, y) { 
    return x + y; 
    }, 

    multiply: function(x, y) { 
    return x * y; 
    } 
}; 

呼叫代理(c)就這樣將返回總和(代理對象)和繁殖()功能。但是,由於proxy()函數中member變量的範圍,它將始終調用c中的最後一個引用函數 - 在本例中爲multiply()。

var cProxy = proxy(c); 

//this should call c.sum, but instead calls c.multiply 
cProxy.sum({ 
    x: 3, 
    y: 8 
}); 

我該如何引用proxy()函數中的正確函數,以便調用正確的方法?

+0

封閉爲什麼你不只是做'代理[員] = C [員]'? – Markasoftware 2014-11-09 00:47:32

+0

上面的代碼被簡化了。在實際的實現中,代理會在調用c中的原始方法之前處理web請求並處理請求數據,因此這是不可能的。如下面的答案中所示,我能夠使用閉包來工作。 – subeeshb 2014-11-09 18:10:51

回答

1

對我下面的工作,只是創建成員

var proxy = function(c) { 
    var proxy = {}; 
    for(var member in c) { 
    !function(member){ 
     var args = c[member].toString().match (/function\s*\w*\s*\((.*?)\)/)[1].split (/\s*,\s*/); 
     proxy[member] = function(params) { 
      var methodArgs = args.map(function(argName) { 
      return params[argName]; 
      }); 
      return c[member].apply(c, methodArgs); 
     } 
    }(member) 
    } 
    return proxy; 
}; 



console.log(cProxy.sum({x: 3,y: 8})) // returns 11 
console.log(cProxy.multiply({x: 3,y: 8})) //returns 24 
+0

謝謝,這工作! – subeeshb 2014-11-09 18:07:21

1

一種方法是將循環內部封裝到一個函數中以創建另一個範圍。它看起來雖然怪異:

proxy[member] = (function(member) { 
     return function(params) { 
      var methodArgs = args.map(function(argName) { 
       return params[argName]; 
      }); 
      return c[member].apply(c, methodArgs); 
     }; 
    })(member); 

演示:http://jsfiddle.net/rudiedirkx/t5ovkrw9/

另一種方法是使用let member in c,這將創建一個比var稍小的範圍,但let是不是在大多數瀏覽器呢。

還有一種方法是使用.bind來將參數或上下文粘貼到函數中。這實際上並不奏效,因爲您已經在使用上下文和參數。

+0

謝謝!這將會奏效。我選擇使用其他答案,因爲代碼會更清晰。 – subeeshb 2014-11-09 18:08:29

+0

只要你知道它的意思。爲什麼會有'!'?什麼是關閉業務?爲什麼它首先不起作用? – Rudie 2014-11-09 19:51:27