Javascript: Add method to all objects in array - Stack Overflow

Imagine the following code:$.get( "ajaxgetColorData.php", function( data ) {this.colorData =

Imagine the following code:

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

now envision that the value of 'data' is:

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

Question 1

Now, after I download the data, let's say that I want to add a method, "colorStartsWithR" to every entry in the array. I "think" that rather than define it on every single member of the array, I could somehow define this method on the prototype. But, I'm not sure that I can do that because these objects were not created by me, but were returned by $.get, so it's not clear to me if I'm thinking in the right direction.

Question 2

And to take it a bit further, what if I wanted to add a property to every member of the array, specifically:

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

This way, I can bind (via knockoutjs) the list and include a checkbox. In this case, I question whether or not the prototype would e in handy because each member should get its own ko.observable property. A quick instinct is to do something like:

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

and that works fine, but imagine that there is more than one way to retrieve a list of colors, or that a user can create new color instances, and that the customization I did above is more plicated. I would now need to duplicate the above "add-on" logic. Is there a smarter way?

Having spent most of my time in strongly-typed languages, sometimes these things aren't as obvious to me. Thanks for any suggestions...

-Ben

Imagine the following code:

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

now envision that the value of 'data' is:

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

Question 1

Now, after I download the data, let's say that I want to add a method, "colorStartsWithR" to every entry in the array. I "think" that rather than define it on every single member of the array, I could somehow define this method on the prototype. But, I'm not sure that I can do that because these objects were not created by me, but were returned by $.get, so it's not clear to me if I'm thinking in the right direction.

Question 2

And to take it a bit further, what if I wanted to add a property to every member of the array, specifically:

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

This way, I can bind (via knockoutjs) the list and include a checkbox. In this case, I question whether or not the prototype would e in handy because each member should get its own ko.observable property. A quick instinct is to do something like:

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

and that works fine, but imagine that there is more than one way to retrieve a list of colors, or that a user can create new color instances, and that the customization I did above is more plicated. I would now need to duplicate the above "add-on" logic. Is there a smarter way?

Having spent most of my time in strongly-typed languages, sometimes these things aren't as obvious to me. Thanks for any suggestions...

-Ben

Share Improve this question edited Jan 8, 2014 at 1:50 BenjiFB asked Jan 8, 2014 at 1:45 BenjiFBBenjiFB 4,74110 gold badges48 silver badges59 bronze badges 1
  • Why add the function to each object? Just make a function that accepts the objects as a parameter. – Kevin Bowersox Commented Jan 8, 2014 at 1:48
Add a ment  | 

3 Answers 3

Reset to default 2

Well, those objects don't have a special prototype, so you can't add members to it. I think these are the alternatives:

1) Add the members to each instance (I know you don't like it, but it's an option). I'd go for this option

2) Just create a method, and pass each object as a parameter or as this with fn.call()

3) Create a "class" with the added members, then create instances of it passing the original object in the constructor. Not ideal, but maybe you have to do it.

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

   //if you want all properties to be copied dynamically, unment 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

Then, to apply it

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

Hope this helps. Cheers

One option is to create a wrapper object and add the new method to the wrappers prototype:

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 Fiddle: http://jsfiddle/ywrK6/1/

Another option is to just create a function that accepts the object as an argument:

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

The objects in your array are plain objects of the type Object. To add methods to the prototype of those objects, you'd have to add the methods to the Object type like this:

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

That would work in this case, but it is really not remended. The better solutions are to either change the objects in the array to be a different type of object that has it's own prototype to which you can add colorStartsWithR() to OR just use a utility function to test a name to see if starts with "R"`.

Here are examples:

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

Then, you could do:

this.colorData[1].colorStartsWithR();

Or, just a utility function:

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);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744354690a4570172.html

相关推荐

  • Javascript: Add method to all objects in array - Stack Overflow

    Imagine the following code:$.get( "ajaxgetColorData.php", function( data ) {this.colorData =

    7天前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信