web-dev-qa-db-fra.com

Pouvons-nous convertir un objet générique en un type d'objet personnalisé en javascript?

Par exemple, j'ai déjà cet objet quelque part dans le code, c'est un objet générique:

var person1={lastName:"Freeman",firstName:"Gordon"};

J'ai le constructeur d'un objet Person:

function Person(){
 this.getFullName=function(){
  return this.lastName + ' ' + this.firstName;
 }
}

Existe-t-il une syntaxe simple nous permettant de convertir person1 en un objet de type Person?

42
bobo

La réponse de @PeterOlson peut être corrigée dans la journée, mais il semble que Object.create ait été modifié . J'irais pour le constructeur de copie comme @ user166390 a dit dans les commentaires.
La raison pour laquelle j'ai nécromancié ce post est parce que j'avais besoin d'une telle implémentation.

De nos jours, nous pouvons utiliser Object.assign (crédits de la solution @SayanPal) & ES6:

class Person {
  constructor(obj) {
    obj && Object.assign(this, obj);
  }

  getFullName() {
    return `${this.lastName} ${this.firstName}`;
  }
}

Usage:

const newPerson = new Person(person1)
newPerson.getFullName() // -> Freeman Gordon

ES5 réponse ci-dessous

function Person(obj) {
    for(var prop in obj){
        // for safety you can use the hasOwnProperty function
        this[prop] = obj[prop];
    }
}

Usage:

var newPerson = new Person(person1);
console.log(newPerson.getFullName()); // -> Freeman Gordon

En utilisant une version plus courte, 1.5 liner:

function Person(){
    if(arguments[0]) for(var prop in arguments[0]) this[prop] = arguments[0][prop];
}

jsfiddle

33
A1rPun

Non.  

Mais si vous souhaitez traiter votre objet person1 comme s'il s'agissait d'une Person, vous pouvez appeler des méthodes sur le prototype de Person sur person1 avec call:

Person.prototype.getFullNamePublic = function(){
    return this.lastName + ' ' + this.firstName;
}
Person.prototype.getFullNamePublic.call(person1);

Cela ne fonctionnera évidemment pas pour les méthodes privilégiées créées dans le constructeur Person, comme votre méthode getFullName

6
Adam Rackis

Ce n'est pas exactement une réponse, mais plutôt partager mes conclusions et, espérons-le, obtenir des arguments critiques pour/contre, car je ne suis pas au courant de son efficacité.

J'ai eu récemment besoin de le faire pour mon projet. Je l'ai fait en utilisant Object.assign , plus précisément, il est fait quelque chose comme ceci: Object.assign(new Person(...), anObjectLikePerson).

Voici un lien vers mon JSFiddle , ainsi que la partie principale du code:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = function() {
    return this.lastName + ' ' + this.firstName;
  }
}

var persons = [{
  lastName: "Freeman",
  firstName: "Gordon"
}, {
  lastName: "Smith",
  firstName: "John"
}];

var stronglyTypedPersons = [];
for (var i = 0; i < persons.length; i++) {
  stronglyTypedPersons.Push(Object.assign(new Person("", ""), persons[i]));
}
3
Sayan Pal

Ceci emprunte à quelques autres réponses ici, mais je pensais que cela pourrait aider quelqu'un. Si vous définissez la fonction suivante sur votre objet personnalisé, vous disposez alors d'une fonction d'usine à laquelle vous pouvez transmettre un objet générique et qui vous renverra une instance de la classe.

CustomObject.create = function (obj) {
    var field = new CustomObject();
    for (var prop in obj) {
        if (field.hasOwnProperty(prop)) {
            field[prop] = obj[prop];
        }
    }

    return field;
}

Utiliser comme ça

var typedObj = CustomObject.create(genericObj);
1
Obi Onuorah

Ceci est juste une synthèse de la réponse Sayan Pal dans un format plus court, à la manière ES5:

var Foo = function(){
    this.bar = undefined;
    this.buzz = undefined;
}

var foo = Object.assign(new Foo(),{
    bar: "whatever",
    buzz: "something else"
});

Je l’aime bien parce que c’est le plus proche de la très nette initialisation d’objets dans .Net:

var foo = new Foo()
{
    bar: "whatever",
    ...
1
pasx

Cela a fonctionné pour moi. C'est simple pour des objets simples.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  getFullName() {
    return this.lastName + " " + this.firstName;
  }

  static class(obj) {
    return new Person(obj.firstName, obj.lastName);
  }
}

var person1 = {
  lastName: "Freeman",
  firstName: "Gordon"
};

var gordon = Person.class(person1);
console.log(gordon.getFullName());

Je recherchais également une solution simple, et c’est ce que j’ai proposé, à partir de toutes les autres réponses et de mes recherches. Fondamentalement, la classe Person a un autre constructeur, appelé 'class', qui fonctionne avec un objet générique du même 'format' que Person . J'espère que cela pourra aussi aider quelqu'un.

0
Orwol Chiles