2014-11-05 88 views
1

什麼我真的很爲創建對象的方法/屬性是類似下面的代碼:的Javascript:通過遍歷數組

var painter = {}; // An object to hold methods 
var colors = ['blue', 'red', 'green', 'yellow']; // The names of methods to be defined 
colors.forEach(function(color) { 
    painter.defineMethod(color, function(){ console.log(color); }); 
}); 

painter.blue() // writes blue 
painter.red() // writes red 
etc. 

的painter.defineMethod()是關鍵。

我必須定義幾個(向上40)方法的對象,他們都基本上是相同的,與真正意義調用另一個方法微小但可預見的變化。例如:

painter.blue = function(tool) { 
    painter.draw('blue', tool); // Would paint blue with a brush or pencil or whatever. 
} 

是這樣的可能,或者我堅持明確定義所有這些屬性?這種方式或其他方式對性能有什麼好處?

什麼會在具有可變的變量或神奇的方法是在Javascript中證明很難(甚至不可能)語言很容易。雖然我承認JavaScript不是我的特長。

謝謝!

回答

2

你的直覺是正確的,你確實可以自動完成:

colors.forEach(function(color) { 
    painter[color] = function(tool) { 
     painter.draw(color, tool); 
    }; 
}); 

有在這裏工作兩件事情:

  1. 在JavaScript中,您可以訪問(獲取或設置)屬性使用點符號和屬性名文字obj.foo),或使用括號符號和屬性名稱字符串obj["foo"])。在後一種情況下,字符串可以是任何表達式的結果,包括變量查找。所以painter[color] = ...分配給它的名字來源於color參數的屬性。

  2. 然後,我們使用的事實是,我們創建的函數是對調用迭代函數的閉包,我們給了forEach,所以我們可以在該函數中使用color參數。即使調用迭代函數返回,因爲我們創造了通話中的功能,並保持對它的引用,該函數保持對上下文的引用(這是一個關閉在上下文中),所以我們可以依靠color參數在那裏。更多關於關閉(在我的博客):Closures are not complicated

但由於painter.draw需要的顏色作爲第一個參數和工具作爲其第二個,還有,如果你願意,你可以做到這一點,雖然第二個辦法:你可以「curry」的顏色參數爲使用Function#bind方法(一ES5功能,可以在越來越小數量的舊引擎來墊高沒有它)對painter.draw

colors.forEach(function(color) { 
    painter[color] = painter.draw.bind(painter, color); 
}); 

Function#bind返回功能當被調用時,用給定的調用原始函數值(painter在上面的例子)和你提供給bind任何進一步的參數,隨後給予原始任何參數。一個簡單的例子可能會做出更加清晰:

function func(a, b) { 
 
    snippet.log("this.name = " + this.name); 
 
    snippet.log("a = " + a); 
 
    snippet.log("b = " + b); 
 
} 
 

 
var o1 = { 
 
    name: "o1" 
 
}; 
 
var o2 = { 
 
    name: "o2" 
 
}; 
 

 
var o1boundfoo = func.bind(o1, "foo"); 
 
var o2boundbar = func.bind(o2, "bar"); 
 

 
o1boundfoo("nifty"); // Shows: 
 
        // this.name = o1 
 
        // a = foo 
 
        // b = nifty 
 

 
o2boundbar("nifty"); // Shows: 
 
        // this.name = o2 
 
        // a = bar 
 
        // b = nifty
<!-- Temporary snippet object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

+1

哇!謝謝。這不僅解決了我的問題,而且解決了一些問題。你知道,我從來沒有喜歡過Javascript(我喜歡像真正類的python這樣的更多結構化語言),但是我學得越多,我越認識到我自己的無知,我不喜歡:) – Apollo 2014-11-05 17:49:10

+0

@Apollo:是的,發生了這樣的事情許多。現在我發現,當我用一種不太靈活的語言(Java說)工作時,我真的錯過了* JavaScript的靈活性。 :-)(順便說一下,如果你想要的東西就像JS中的類一樣,下面是我使用的幫助器:http://code.google.com/p/lineagejs/。它仍然是原型繼承[這很棒],但是帶有一些課堂的特徵。) – 2014-11-05 18:06:07