Javascript:向数组中的所有对象添加方法

时间:2014-01-08 01:45:13

标签: javascript arrays function-prototypes function-constructor

想象一下以下代码:

$.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

3 个答案:

答案 0 :(得分:2)

嗯,这些对象没有特殊的原型,因此您无法向其添加成员。我认为这些是替代方案:

1)将成员添加到每个实例(我知道你不喜欢它,但它是一个选项)。我会选择这个选项

2)只需创建一个方法,并将每个对象作为参数或this传递给fn.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
}

希望这会有所帮助。干杯

答案 1 :(得分:2)

一种选择是创建一个包装器对象并将新方法添加到包装器原型中:

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";
}

答案 2 :(得分:1)

数组中的对象是Object类型的普通对象。要将方法添加到这些对象的原型,您必须将方法添加到Object类型,如下所示:

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

在这种情况下可行,但实际上并不推荐。更好的解决方案是将数组中的对象更改为具有自己的原型的不同类型的对象,您可以将colorStartsWithR()添加到OR,只需使用实用程序函数来测试名称以查看是否以“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);