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

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

function Animal(){ 
    var self=this; 

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

服務器響應發揮作用的實例( 「類」):鑄造純JavaScript中的對象

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

我從服務器獲取人陣。我想要將通用Person數組轉換爲類型Person數組。所以,我可以使用

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

我創辦了JavaScript的

Object.create(Person,person1); 

但我想跨瀏覽器的版本,它與陣列支持

ObjectArray.create(Person,persons); 

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

你的問題還不清楚。 JavaScript數組不是鍵入的。 (當然也有那些類型,但基本數組不是新陣列狀的東西。) – Pointy 2012-08-04 16:07:09

+0

你說你要使用的代碼意味着,你從服務器檢索的人數組包含對象,例如'[{動物:[...]},{動物:[......]}] - 這是你的意思嗎? – JMM 2012-08-04 16:14:42

+0

我已經添加了示例代碼。我認爲問題現在已經很清楚了。 – ozz 2012-08-04 16:19:21

回答

15

創建在JavaScript對象要求其構造函數的調用。所以,起初你需要找到正確的參數,這可能並不總是屬性。之後,您可以將JSON解析對象的所有公共屬性重新分配給創建的實例。

一般的解決方案是每個構造函數都接受任何看起來像實例(包括實例)的對象並對它們進行克隆。所有創建適當實例所需的內部邏輯都將位於正確的位置。

或大於超載的構造更好的可能是創建類,從他們需要的對象,並創建實例的靜態方法:

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

你的情況很簡單,因爲你不」沒有任何爭論,只有公共財產。要改變{personName:John,animals:[]}對象實例,使用此:

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

您還可以使用Object.extend功能對於這一點,你應該有一個可用的(如jQuery的):

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

Animal實例的創建作品類似。

由於JSON不運有關的類的任何信息,您必須知道之前的結構。你的情況將是:

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

順便說一句,你run方法很可能要在Animal.prototype對象,而不是每個實例的補充。

+0

非常感謝,你爲我節省了一大堆時間! – Tone 2013-12-05 16:48:36

1

首先全部:在JavaScript中你沒有像我這樣的課程n C++,Java或C#。所以你不能真的有一個類型數組。

你在做什麼應該基本上適用於變量,但不適用於函數。所以你必須先添加函數。看看下面的代碼來獲得一個想法。

<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

分配運行功能非常有趣。我喜歡它。 – ozz 2012-08-04 20:49:25

1

如何在Person類上創建靜態方法,它將接受您的服務器響應並創建所需的變量。

這只是一個想法。請看看這是否符合你的問題。

//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

修復您的運行變量。你想用'p'還是'i'?另外,我不認爲這應該是Person類的statice方法 - 爲什麼在JSON格式更改時更改類? – Bergi 2012-08-04 18:49:35

+0

謝謝Bergi。我將我的變量更新爲p。關於靜態方法。是的,這是Person類的靜態方法。當然,JSON格式不會改變。如果它發生變化,那麼在任何情況下它都不會自動轉換爲Person對象。因此,爲了兼容性,JSON格式應該始終具有相同的格式。 – 2012-08-04 19:20:42

2

好像你有有一些原型方法的類,你只是想能夠讓你的對象使用這些方法。 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(); 
}); 

這都可能是一個更容易(和我們能夠避免所有的複製)如果大家支持__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

這不適用於'Object.create',並且不會以這種方式工作。 – Bergi 2012-08-04 17:56:25

+0

@Bergi我注意到了這一點,有一個新的解決方案 – 2012-08-04 18:40:01

+0

更新它是什麼'surrogateConstructor'好,你就不能使用正常的嗎?如果你想避免調用它,也可以使用'Object.create(constructor.prototype)'。 – Bergi 2012-08-04 19:24:47