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