6

想象以下代碼:使用Javascript:對所有對象添加方法在陣列

$.get("ajax/getColorData.php", function(data) { 
    this.colorData = data; 
}); 

現在設想, '數據' 的值是:

this.colorData = [ 
    { 
     colorName: 'Red', 
     colorIsInRainbow:true 
    }, 
    { 
     colorName: 'Orange', 
     colorIsInRainbow: true 
    }, 
    { 
     colorName: 'Magenta', 
     colorIsInRainbow: false 
    } 
]; 

問題1

現在,在下載數據之後,假設我想爲數組中的每個條目添加一個方法「colorStartsWithR」。我「認爲」,而不是在數組的每一個成員上定義它,我可以以某種方式在原型上定義這種方法。但是,我不確定我能做到這一點,因爲這些對象不是由我創建的,而是由$ .get返回的,所以我不清楚我是否正朝着正確的方向思考。

問題2

而且把它遠一點,如果我想要一個屬性添加到陣列中的每個成員,特別是:

{ 
     colorName: 'Magenta', 
     colorIsInRainbow: false, 
     userClickedThisColor:ko.observable() 
    } 

這樣一來,我可以綁定(通過knockoutjs)列表幷包括一個複選框。在這種情況下,我質疑原型是否會派上用場,因爲每個成員都應該擁有自己的ko.observable屬性。一個快速的本能是做這樣的事情:

for (var i=0;i<this.colorData.length;i++) 
{ 
this.colorData[i].userClickedThisColor=ko.observable() 
} 

和工作正常,但試想,有檢索顏色列表,或者用戶可以創建新的顏色實例的方法不止一種,那我上面做的定製比較複雜。我現在需要複製上面的「附加」邏輯。有更聰明的方法嗎?

我的大部分時間都花在強類型語言上,有時候這些東西對我來說並不那麼明顯。感謝您的任何建議...

-Ben

+0

爲什麼功能添加到每個對象?只需製作一個接受對象作爲參數的函數即可。 –

回答

2

那麼,這些對象不具有特殊的原型,所以你不能添加成員。我認爲這些是替代品:

1)將成員添加到每個實例(我知道你不喜歡它,但它是一個選項)。我會去爲這個選項

2)只需創建一個方法,並通過每一個對象作爲參數或thisfn.call()

3)與添加的成員創建一個「類」,然後創建的實例它在構造函數中傳遞原始對象。不理想,但也許你必須這樣做。

function Color(plainObj){ 
    this.colorName: plainObj.colorName; 
    this.colorIsInRainbow: plainObj.colorIsInRainbow; 

    //if you want all properties to be copied dynamically, uncomment the following: 
    //for(var key in plainObj) this[key] = plainObj[key];     

    this.userClickedThisColor = ko.observable() 
    ... 
} 
Color.prototype.colorStartsWithR = function() { 
    return this.colorName.charAt(0) == "R"; 
}; 

//etc 

然後,將其應用

for(var i=0; i<colorData.length; i++){ 
    colorData[i] = new Color(colorData[i]); //Overwrites original colorData array 
} 

希望這有助於。歡呼聲

+0

謝謝埃德加!我只能將一篇文章標記爲答案,儘管你的文章也很有幫助。 – BenjiFB

+0

歡迎。我更新了我的答案,請檢查它 –

+0

謝謝!所以,只需確認一下這一行: Color.prototype.userClickedThisColor = ko.observable();我是否正確,儘管在原型中定義了,每個實例確實會得到它自己的獨立副本? – BenjiFB

1

數組中的對象是Object類型的普通對象。要添加方法對這些對象的原型,你不得不方法添加到Object類型是這樣的:

Object.prototype.colorStartsWithR = function() { 
    return this.colorName.substr(0,1) == "R"; 
} 

將在此情況下工作,但它確實是不推薦使用。更好的解決方案是將數組中的對象更改爲具有自己的原型的不同類型的對象,您可以將其添加到colorStartsWithR()或者只是使用效用函數來測試名稱以查看是否以「R」開頭` 。

下面舉例說明:

function colorObj(color, inRainbow) { 
    this.colorName = color; 
    this.colorIsInRainbow = inRainbow; 
} 

colorObj.prototype.colorStartsWithR = function() { 
     return this.colorName.substr(0,1) == "R"; 
} 

this.colorData = [ 
    new colorObj('Red', true), 
    new colorObj('Orange, true), 
    new colorObj('Magenta, false) 
}; 

然後,你可以這樣做:

this.colorData[1].colorStartsWithR(); 

或者,只是一個效用函數:

var colorData = [ 
    { 
     colorName: 'Red', 
     colorIsInRainbow:true 
    }, 
    { 
     colorName: 'Orange', 
     colorIsInRainbow: true 
    }, 
    { 
     colorName: 'Magenta', 
     colorIsInRainbow: false 
    } 
]; 

function startsWithR(str) { 
    return str.substr(0,1) == "R"; 

} 

startsWithR(colorData[1].colorName); 
+0

謝謝jfriend00!我只能將一篇文章標記爲看起來的答案,儘管你的文章也很有幫助,我非常感謝這些詳細的例子。 – BenjiFB

2

一種選擇是創建一個包裝器對象並將新方法添加到w中說唱歌手原型:

var colorData = [ 
    { 
     colorName: 'Red', 
     colorIsInRainbow:true 
    }, 
    { 
     colorName: 'Orange', 
     colorIsInRainbow: true 
    }, 
    { 
     colorName: 'Magenta', 
     colorIsInRainbow: false 
    } 
]; 

function ColorDataWrapper(colorData){ 
    this.colorData = colorData; 
} 

ColorDataWrapper.prototype.colorStartsWithR = function(){ 
    return this.colorData.colorName.substring(0,1) == "R"; 
}; 

for(var i = 0; i < colorData.length; i++){ 
    colorData[i] = new ColorDataWrapper(colorData[i]); 
} 

alert(colorData[0].colorStartsWithR()); 
alert(colorData[1].colorStartsWithR()); 

JS小提琴:http://jsfiddle.net/ywrK6/1/

另一種選擇是隻創建一個接受的對象作爲參數的函數:

function colorStartsWithR(obj){ 
    return obj.colorData.colorName.substring(0,1) == "R"; 
} 
+0

謝謝凱文! – BenjiFB

+0

主要針對我的筆記添加評論:看起來在此解決方案中,ColorDataWrapper函數創建的封裝器級別高於其他解決方案,這意味着不需要爲每個成員接受參數(jfriend00的示例) ,或者做動態屬性枚舉(埃德加的例子)。這很好,因爲它很簡單,但在該方法中,您在方法colorStartsWithR中有一個額外的間接級別(這似乎是一個簡單的小代價)。只是想指出這一點(如果我理解正確)。 – BenjiFB

+0

如果要循環遍歷數組中的所有元素,則可以直接將方法'colorStartsWithR()'添加到數組中的每個對象。該方法不必在原型上 - 它可以直接添加到對象。沒有必要用不同類型的對象替換該對象。 – jfriend00