6

想象一下下面的代码:

$.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()
}

这很好用,但是想象一下检索颜色列表的方法不止一种,或者用户可以创建新的颜色实例,并且我上面所做的自定义更加复杂。我现在需要复制上面的“附加”逻辑。有没有更聪明的方法?

我大部分时间都在使用强类型语言,有时这些事情对我来说并不那么明显。感谢您的任何建议...

-本

4

3 回答 3

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
}

希望这可以帮助。干杯

于 2014-01-08T01:51:31.413 回答
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";
}
于 2014-01-08T01:54:51.260 回答
1

数组中的对象是 type 的普通对象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);
于 2014-01-08T01:52:48.893 回答