将普通对象转换为 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 14:25:22  来源:igfitidea点击:

Casting plain objects to function instances ("classes") in javascript

javascriptcasting

提问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.assignfunctionality (or e.g. jQuery.extendpre-ES6) for this:

您还可以为此使用Object.assign功能(或例如jQuery.extendES6 之前的版本):

var personInstance = Object.assign(new Person(), personLiteral);

The creation of the Animalinstances 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 runmethods seems likely to be added on the Animal.prototypeobject 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 );