将普通对象转换为 javascript 中的函数实例(“类”)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11810028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Casting plain objects to function instances ("classes") in javascript
提问by ozz
function Person() {
var self = this;
self.personName="";
self.animals=[];
}
function Animal(){
var self=this;
self.animalName="";
self.run=function(meters){
.....
}
}
Server response:
服务器响应:
[{personName:John,animals:[{animalName:cheetah},{animalName:giraffe}]} , {personName:Smith,animals:[{animalName:cat},{animalName:dog}]} ]
I'm getting Person array from server. I want to cast generic Person array to typed Person array. So I can use
我正在从服务器获取 Person 数组。我想将通用 Person 数组转换为类型化的 Person 数组。所以我可以使用
persons[0].Animals[2].Run();
I founded Javascript's
我创立了 Javascript
Object.create(Person,person1);
But I want cross-browser version of it with array support
但我想要它的跨浏览器版本并支持数组
ObjectArray.create(Person,persons);
or
或者
Object.create(Person[],persons);
回答by Bergi
Creating an object in JavaScript requires the invocation of its constructor. So, at first you will need to find the correct arguments, which may not always be just properties. After that, you can reassign all public properties from the JSON-parsed object to the created instances.
在 JavaScript 中创建对象需要调用其构造函数。因此,首先您需要找到正确的参数,这些参数可能并不总是只是属性。之后,您可以将 JSON 解析对象中的所有公共属性重新分配给创建的实例。
A general solution would be that every constructor accepts any objects that look like instances (including real instances) and clones them. All the internal logic needed to create proper instances will be located in the right place then.
一般的解决方案是每个构造函数都接受任何看起来像实例(包括真实实例)的对象并克隆它们。创建正确实例所需的所有内部逻辑都将位于正确的位置。
Or even better than overloading the constructor might be to create a static method on your class that takes objects and creates instances from them:
或者甚至比重载构造函数更好的方法可能是在您的类上创建一个静态方法,该方法接受对象并从中创建实例:
Person.fromJSON = function(obj) {
// custom code, as appropriate for Person instances
// might invoke `new Person`
return …;
};
Your case is very simple, as you don't have any arguments and only public properties. To change {personName:John,animals:[]}
to an object instance, use this:
您的情况非常简单,因为您没有任何参数,只有公共属性。要更改{personName:John,animals:[]}
为对象实例,请使用以下命令:
var personLiteral = ... // JSON.parse("...");
var personInstance = new Person();
for (var prop in personLiteral)
personInstance[prop] = personLiteral[prop];
You can also use Object.assign
functionality (or e.g. jQuery.extend
pre-ES6) for this:
您还可以为此使用Object.assign
功能(或例如jQuery.extend
ES6 之前的版本):
var personInstance = Object.assign(new Person(), personLiteral);
The creation of the Animal
instances works analogous.
Animal
实例的创建工作类似。
As JSON does not transport any information about the classes, you must know the structure before. In your case it will be:
由于 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]);
}
}
Btw, your run
methods seems likely to be added on the Animal.prototype
object instead of each instance.
顺便说一句,您的run
方法似乎很可能被添加到Animal.prototype
对象而不是每个实例上。
回答by Juan Mendes
It seems like you have classes that have some prototype methods and you'd just like to be able to make your objects use those methods. http://jsfiddle.net/6CrQL/3/
似乎您的类具有一些原型方法,并且您只是希望能够使您的对象使用这些方法。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();
});
?This could all be a lot easier (and we could avoid all the copying) if everybody supported the __proto__
property http://jsfiddle.net/6CrQL/2/
?这都可能是一个更容易(和我们能够避免所有的复制),如果大家都支持的__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();
});?
回答by Preli
First of all: In JavaScript you don't have classes like in C++, Java or C#. So you cannot really have a typed array.
首先:在 JavaScript 中,你没有像 C++、Java 或 C# 那样的类。所以你不能真正拥有一个类型化的数组。
What you are doing should basically work for variables, but not for functions. So you would have to add the functions first. Have a look at the following code to get an 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>
回答by Sasidhar Vanga
How about creating a Static method on Person Class, which will accept your server response and create required variables.
如何在 Person 类上创建一个静态方法,它将接受您的服务器响应并创建所需的变量。
This is just an idea. Please see if this fits in your problem.
这只是一个想法。请看看这是否适合您的问题。
//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 );