简体   繁体   中英

How to convert a literal object into user defined object in javascript?

Writing a ton of web applications leveraging JSON/AJAX, I find myself returning tons literal javascript objects (JSON). For example, I may be request all the Cats from GetCats.asp. It would return:

[
  { 'id': 0, 'name': 'Persian' },
  { 'id': 1, 'name': 'Calico' },
  { 'id': 2, 'name': 'Tabby' }
]

Now, these are all Cat objects with behaviors. However, if I define a Cat object, function Cat() { }, I know of no EFFICIENT way to coax these literal objects into the behaviors of a user defined object.

I can do this by brute force of iterating through them and assigning functions, but it's not going to be pretty. Is there a nice, one line(or few), way of somehow "casting" this behavior onto these literal objects?

There's no getting around the fact that you will have to iterate through all of your simple objects and change them to a different kind of object. You cannot avoid the loop. That being said you could create a constructor that takes a simple object like this and copies those values into the new instance.

Like this:

function Cat(c) {
  this.id = c.id;
  this.name = c.name;
}
Cat.prototype.meow = function() {alert('meow');}
Cat.prototype.displayName= function() {alert(this.name);}

var cats = [
  { 'id': 0, 'name': 'Persian' },
  { 'id': 1, 'name': 'Calico' },
  { 'id': 2, 'name': 'Tabby' }
];

for (i=0,len=cats.length; i<len; i++) {
  cats[i] = new Cat(cats[i]);
}

cats[0].meow();  // displays "meow"
cats[0].displayName();  // display "Persian"

If you're using the json2 parser (or another one with a compatible interface), you can simply provide a callback to replace the raw objects with custom objects:

var catSource = '[ { "id": 0, "name": "Persian" }, { "id": 1, "name": "Calico" }, { "id": 2, "name": "Tabby" } ]';

function Cat(id, name)
{
   this.id = id;
   this.name = name;
}
Cat.prototype = 
{
   toString: function()
   {
      return this.name;
   }
};

function doStuff()
{
   var cats = JSON.parse(catSource, function(key, val)
   {
      // some expression to detect the type of val 
      if ( val.id !== undefined && val.name !== undefined )
         return new Cat(val.id, val.name);
      return val;
   });
   alert(cats);
}

do you use prototype framework? if yes - here is an example


var cats = [
    {id: 15, name: 'Tables', count:45 },
    {id: 23, name: 'Chairs', count:34 }
];
var catsObjects = [];
cats.each(function(item){
    var newObject = new Cat();
    Object.extend(newObject, item);
    catsObjects.push(newObject);
});

basically Array.each function is the same as "for i < Array.length"
and Object.extend is the same as property-by-property adding properties to newObject

Extending @Benry's answer.

I find that having an extend function to copy properties of one object onto another is essential. There is a semi-tradition for putting it onto Object; Object.extend() exists in many smaller libraries (NB: this is not the same as Object.prototype).

Object.extend = function ( take, give ) {
  for (var k in give) {
    if (give.hasOwnProperty(k)) {
      take[k] = give[k];
    }
  }
  return take;
}

This has the plus that you can use nice readable literal notation when writing your code:

function Cat (c) {
  Object.extend( this, ( c || this.defaults )  );
}

Object.extend(Cat.prototype, {

  meow : function() {
    alert( 'Meow, my name is ' + this.name );
  },

  defaults : {
    name : 'I have no name', 
    id   : null
  }

});

You can then create your army of cats quite simply:

var cats = [
  { 'id': 0, 'name': 'Persian' },
  { 'id': 1, 'name': 'Calico' },
  { 'id': 2, 'name': 'Tabby' }
];

for (i=0,len=cats.length; i<len; i++) {
  cats[i] = new Cat( cats[i] );
}

cats[0].meow();  // displays "meow, my name is Persian"

Assign each object an appropriate prototype:

var list = [
  { 'id': 0, 'name': 'Persian' },
  { 'id': 1, 'name': 'Calico' },
  { 'id': 2, 'name': 'Tabby' }
];


for (obj in list)
{
  obj.prototype = new Cat();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM