2012-08-04 8 views
13
function Person() { 
     var self = this; 

     self.personName=""; 
     self.animals=[]; 
} 

function Animal(){ 
    var self=this; 

    self.animalName=""; 
    self.run=function(meters){ 
     ..... 
    } 
} 

respuesta del servidor:Conversión de objetos lisos para funcionar casos ("clases") en javascript

[{personName:John,animals:[{animalName:cheetah},{animalName:giraffe}]} , {personName:Smith,animals:[{animalName:cat},{animalName:dog}]} ] 

Me estoy poniendo matriz persona desde el servidor. Quiero lanzar una matriz de persona genérica a una matriz de persona tipada. Así que se puede utilizar

persons[0].Animals[2].Run(); 

fundé

Object.create(Person,person1); 

Pero quiero versión multi-navegador de Javascript de ella con el apoyo conjunto

ObjectArray.create(Person,persons); 

o

Object.create(Person[],persons); 
+4

Su pregunta no está clara. Las matrices de JavaScript no están escritas. (Bueno, hay nuevas cosas tipo matriz que se escriben pero las matrices básicas no). – Pointy

+0

El código que dice que quiere usar implica que la matriz Persona que está recuperando del servidor contendrá objetos, p. '[{Animal: [...]}, {Animal: [...]}]' - ¿es eso lo que quieres decir? – JMM

+0

Agregué el código de muestra. Creo que la pregunta es clara ahora. – ozz

Respuesta

15

Creación de un objeto en JavaScript requiere la invocación de su constructor . Entonces, al principio necesitarás encontrar los argumentos correctos, que no siempre pueden ser solo propiedades. Después de eso, puede reasignar todas las propiedades públicas del objeto analizado por JSON a las instancias creadas.

Una solución general sería que cada constructor acepta objetos que parecen instancias (incluidas las instancias reales) y los clona. Toda la lógica interna necesaria para crear instancias adecuadas se ubicará en el lugar correcto.

o incluso mejor que la sobrecarga del constructor podría ser la creación de un método estático en su clase que toma objetos y crea instancias de ellos:

Person.fromJSON = function(obj) { 
    // custom code, as appropriate for Person instances 
    // might invoke `new Person` 
    return …; 
}; 

Su caso es muy simple, como usted don' t tiene argumentos y solo propiedades públicas.Para cambiar {personName:John,animals:[]} a una instancia de objeto, utilice esto:

var personLiteral = ... // JSON.parse("..."); 
var personInstance = new Person(); 
for (var prop in personLiteral) 
    personInstance[prop] = personLiteral[prop]; 

También puede utilizar Object.extend funcionalidad para esto, en caso de tener uno disponible (por ejemplo, jQuery):

var personInstance = $.extend(new Person(), personLiteral); 

La creación de los Animal casos funciona análogamente

Como JSON no transporta ninguna información sobre las clases, debe conocer la estructura antes. En su caso, será:

var persons = JSON.parse(serverResponse); 
for (var i=0; i<persons.length; i++) { 
    persons[i] = $.extend(new Person, persons[i]); 
    for (var j=0; j<persons[i].animals; j++) { 
     persons[i].animals[j] = $.extend(new Animal, persons[i].animals[j]); 
    } 
} 

Por cierto, sus métodos run parece probable que se añadan en el Animal.prototype objeto en lugar de cada instancia.

+0

muchas gracias, ¡me salvaste un montón de tiempo! – Tone

1

primer todo: en JavaScript no tienes clases como yo n C++, Java o C#. Entonces realmente no puedes tener una matriz tipada.

Lo que está haciendo debería funcionar básicamente para variables, pero no para funciones. Entonces, debería agregar las funciones primero. Eche un vistazo al siguiente código para tener una idea.

<script type="text/javascript"> 

function Person() { 
     var self = this; 

     self.personName=""; 
     self.animals=[]; 
} 

function Animal(){ 
    var self=this; 

    self.animalName=""; 
    self.run=function(meters){ 
     7/... do something 
    } 
} 

var persons = [{personName:"John",animals:[{animalName:"cheetah"},{animalName:"giraffe"}]} , {personName:"Smith",animals:[{animalName:"cat"},{animalName:"dog"}]} ]; 

//use this to assign run-function 
var a = new Animal(); 

//assign run-function to received data 
persons[0].animals[0].run = a.run; 

//now this works 
persons[0].animals[0].run(); 

</script> 
+0

La asignación de la función de ejecución es muy interesante. Me gustó. – ozz

1

¿Qué le parece crear un método estático en Person Class, que aceptará la respuesta del servidor y creará las variables necesarias.

Esto es solo una idea. Por favor, mira si esto encaja en tu problema.

//Static method 
Person.createObjects = function(response) { 
    var persons = []; 
    for (var p = 0; p < response.length; p++) { 
     //Create Person 
     var person = new Person(response[p].personName); 
     //Create Animals 
     for (var a = 0; a < response[p].animals.length; a++) { 
      var animal = new Animal(response[p].animals[a].animalName); 
      //Push this animal into Person 
      person.animals.push (animal); 
     } 
     //Push this person in persons 
     persons.push (person); 
    } 
    //Return persons 
    return persons; 
} 

//Now Create required persons by passing the server response 
var persons = Person.createObjects (response); 
+0

arregla tus variables de ejecución. ¿Quieres usar 'p' o' i'? Además, no creo que este deba ser un método statice en la clase 'Persona', ¿por qué cambiar la clase cuando cambia el formato JSON? – Bergi

+0

Gracias Bergi. Actualicé mi variable a p. Y con respecto al método estático. Sí, este es un método estático en la clase Persona. Y definitivamente el formato JSON no cambiará. Si cambia, no se convertirá automáticamente en objeto Persona en ningún caso. Entonces, para compatibilidad, el formato JSON siempre debe tener el mismo formato. –

2

Parece como que tiene clases que tienen algunos métodos de prototipo y que sólo le gustaría ser capaz de hacer sus objetos utilizan esos métodos. http://jsfiddle.net/6CrQL/3/

function Person() {} 

Person.prototype.speak = function() { 
    console.log("I am " + this.personName); 
}; 

Person.prototype.runAnimals = function() { 
    this.animals.each(function(animal){ 
     animal.run(); 
    }) 
}; 

function Animal() {} 

Animal.prototype.run = function() { 
    console.log("My Animal " + this.animalName+ " is running"); 
} 

var untypedPersons = [{personName:"John",animals:[{animalName:"cheetah"},{animalName:"giraffe"}]} , {personName:"Smith",animals:[{animalName:"cat"},{animalName:"dog"}]} ]; 

function fromArray(arr, constructor) { 
    return arr.map(function(obj){ 
     var typed = Object.create(constructor.prototype); 
     // Now copy properties from the given object 
     for (var prop in obj) { 
      typed[prop] = obj[prop]; 
     } 
     return typed; 
    }); 
} 

var persons = fromArray(untypedPersons, Person); 
// Attach prototype to each animals list in person 
persons.each(function(person){ 
    person.animals = fromArray(person.animals, Animal); 
}); 

persons.each(function(person){ 
    person.speak(); 
    person.runAnimals(); 
}); 

todo esto podría ser mucho más fácil (y podríamos evitar todo el copiado) si todo el mundo apoya la propiedad __proto__http://jsfiddle.net/6CrQL/2/

persons.each(function(person){ 
    person.__proto__ = Person.prototype; 
    person.animals.each(function(animal){ 
    animal.__proto__ = Animal.prototype; 
    }); 
}); 

persons.each(function(person){ 
    person.speak(); 
    person.runAnimals(); 
});​ 
+0

Este no es un uso adecuado para 'Object.create', y tampoco funcionará de esta manera. – Bergi

+0

@Bergi Lo noté, lo actualicé con una nueva solución –

+0

¿Para qué sirve 'surrogateConstructor', no puedes usar el normal? O use 'Object.create (constructor.prototype)' si quiere evitar llamarlo. – Bergi

Cuestiones relacionadas