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

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

function Animal(){ 
    var self=this; 

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

risposta del server:Casting oggetti semplici a funzionare casi ("classi") in javascript

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

che sto ricevendo gamma persona dal server. Voglio trasmettere l'array Persona generico all'array Persona digitato. Così posso usare

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

ho fondato

Object.create(Person,person1); 

Ma voglio versione cross-browser JavaScript di esso con il supporto di matrice

ObjectArray.create(Person,persons); 

o

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

La tua domanda non è chiara. Gli array JavaScript non sono stati digitati. (Bene, ci sono nuovi elementi simili a una matrice che sono stati digitati ma gli array di base non lo sono.) – Pointy

+0

Il codice che dici di voler utilizzare implica che l'array Persona che stai recuperando dal server conterrà oggetti, ad es. '[{Animal: [...]}, {Animal: [...]}]' - è questo che intendi? – JMM

+0

Ho aggiunto codice di esempio. Penso che la domanda sia chiara ora. – ozz

risposta

15

Creazione di un oggetto in JavaScript richiede l'invocazione del suo costruttore . Quindi, all'inizio dovrai trovare gli argomenti corretti, che potrebbero non essere sempre solo proprietà. Successivamente, è possibile riassegnare tutte le proprietà pubbliche dall'oggetto analizzato da JSON alle istanze create.

Una soluzione generale sarebbe che ogni costruttore accetta qualsiasi oggetto che assomigli a istanze (incluse istanze reali) e li clona. Tutta la logica interna necessaria per creare istanze appropriate verrà quindi posizionata nel posto giusto.

O anche meglio di sovraccaricare il costruttore potrebbe essere quello di creare un metodo statico sulla classe che prende gli oggetti e crea istanze da loro:

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

Il tuo caso è molto semplice, come si don' t avere argomenti e solo proprietà pubbliche.Per cambiare {personName:John,animals:[]} a un'istanza di un oggetto, utilizzare questo:

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

È anche possibile utilizzare Object.extend funzionalità per questo, se avete uno a disposizione (ad esempio jQuery):

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

La creazione delle Animal casi funziona in modo analogo

Poiché JSON non trasferisce alcuna informazione sulle classi, è necessario conoscere la struttura in precedenza. Nel tuo caso sarà:

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

Btw, i vostri metodi run sembra probabile essere aggiunto sulla Animal.prototype oggetto invece di ogni istanza.

+0

grazie mille, mi hai salvato un sacco di tempo! – Tone

1

Prima di tutto: in JavaScript non hai classi come me n C++, Java o C#. Quindi non puoi avere un array tipizzato.

Quello che stai facendo dovrebbe funzionare fondamentalmente per le variabili, ma non per le funzioni. Quindi dovresti prima aggiungere le funzioni. Dai un'occhiata al seguente codice per avere un'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

L'assegnazione della funzione di marcia è così interessante. Mi è piaciuto. – ozz

1

Come creare un metodo statico su Person Class, che accetterà la risposta del server e creerà le variabili richieste.

Questa è solo un'idea. Si prega di vedere se questo si adatta al tuo 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

corregge le variabili in esecuzione. Vuoi usare 'p' o' i'? Inoltre, non penso che questo dovrebbe essere un metodo statice sulla classe 'Person' - perché cambiare la classe quando cambia il formato JSON? – Bergi

+0

Grazie Bergi. Ho aggiornato la mia variabile a p. E riguardo al metodo statico. Sì, questo è un metodo statico sulla classe Person. E sicuramente il formato JSON non cambierà. Se cambia, in ogni caso non si convertirà automaticamente in oggetto Person. Quindi, per compatibilità, il formato JSON dovrebbe sempre avere lo stesso formato. –

2

Sembra che si dispone di classi che hanno alcuni metodi prototipo e si era appena piacerebbe essere in grado di rendere i vostri oggetti utilizzano questi metodi. 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(); 
}); 

tutto questo potrebbe essere molto più facile (e potremmo evitare tutta la copia) se tutti sostenuto la __proto__ proprietà 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

Questo non è un uso adatto per 'Object.create', e non funzionerà anche in questo modo. – Bergi

+0

@Bergi l'ho notato, l'ho aggiornato con una nuova soluzione –

+0

A cosa serve quel surrogateConstructor, non puoi semplicemente usare quello normale? Oppure usa 'Object.create (constructor.prototype)' se vuoi evitare di chiamarlo. – Bergi

Problemi correlati