391 votes

À l’aide de « Object.create » au lieu de « nouveau »

Javascript 1.9.3 / ECMAScript 5 introduit Object.create, Douglas Crockford, entre autres, a été en plaidant pour une longue période de temps. Comment puis-je la remplacer new dans le code ci-dessous avec Object.create?

var UserA = function(nameParam) {
    this.id = MY_GLOBAL.nextId();
    this.name = nameParam;
}
UserA.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();

(À supposer MY_GLOBAL.nextId existe).

Le mieux que je puisse vous arriver, c'est:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();

Il ne semble pas être un avantage, donc je pense que je ne suis pas à l'obtenir. Je suis probablement trop néo-classique. Comment dois-je utiliser Object.create de créer l'utilisateur "bob"?

267voto

CMS Points 315406

Avec un seul niveau de l'héritage, votre exemple ne pouvez pas vous permettre de voir les vrais avantages de l' Object.create.

Cette méthode vous permet de facilement mettre en œuvre héritage différentielle, où les objets peuvent hériter directement à partir d'autres objets.

Sur votre userB exemple, je ne pense pas que votre init méthode doit être publique ou de l'existence même, si vous appelez de nouveau cette méthode sur un objet existant à l'instance, l' id et name propriétés de changement.

Object.create vous permet d'initialiser les propriétés de l'objet à l'aide de son second argument, par exemple:

var userB = {
  sayHello: function() {
    console.log('Hello '+ this.name);
  }
};

var bob = Object.create(userB, {
  'id' : {
    value: MY_GLOBAL.nextId(),
    enumerable:true // writable:false, configurable(deletable):false by default
  },
  'name': {
    value: 'Bob',
    enumerable: true
  }
});

Comme vous pouvez le voir, les propriétés peuvent être initialisé sur le deuxième argument de l' Object.create, avec un littéral d'objet à l'aide d'une syntaxe semblable à celui utilisé par l' Object.defineProperties et Object.defineProperty méthodes.

Il vous permet de définir les attributs de la propriété (enumerable, writableou configurable), ce qui peut être vraiment utile.

56voto

Noel Abrahams Points 3678

Il n'y a vraiment aucun avantage dans l'utilisation de l'Objet.créer(...) sur un nouvel objet.

Ceux qui sont en faveur de cette méthode l'état plutôt ambiguë avantages: "l'évolutivité", ou "plus naturel pour JavaScript" etc.

Cependant, je n'ai pas encore de voir un exemple concret qui montre que l'Objet.créer a aucun avantages sur l'utilisation de nouveau. Au contraire, il y a des problèmes connus avec elle. Sam Elsamman décrit ce qui se passe quand il y a des objets imbriqués et de l'Objet.créer(...) est utilisé:

    var Animal = {
        traits: {},
    }
    var lion = Object.create(Animal);
    lion.traits.legs = 4;
    var bird = Object.create(Animal);
    bird.traits.legs = 2;
    alert(lion.traits.legs) // shows 2!!!

Cela se produit parce que l'Objet.créer(...) préconise une pratique où des données est utilisé pour créer de nouveaux objets; ici, l'Animal datum devient partie du prototype de lion et l'oiseau, et provoque des problèmes comme elle est partagée. Lors de l'utilisation de nouveaux prototypes de l'héritage est explicite:

     function Animal() {
        this.traits = {};
    }

    function Lion() { }
    Lion.prototype = new Animal();
    function Bird() { }
    Bird.prototype = new Animal();

    var lion = new Lion();
    lion.traits.legs = 4;
    var bird = new Bird();
    bird.traits.legs = 2;
    alert(lion.traits.legs) // now shows 4

Concernant, la propriété facultative attributs qui sont passés dans l'Objet.créer(...), ceux-ci peuvent être ajoutés à l'aide de l'Objet.defineProperties(...).

42voto

John Points 389

Objet.créer n'est pas encore la norme sur plusieurs navigateurs, par exemple, IE8, Opera v11.5, Konq 4.3 ne pas l'avoir. Vous pouvez utiliser Douglas Crockford de la version de l'Objet.créer pour les navigateurs, mais cela ne comprend pas le second " initialisation de l'objet du paramètre utilisé dans les CMS de réponse.

Pour la croix-navigateur de code une façon d'obtenir de l'initialisation des objets dans l'intervalle est de personnaliser Crockford de l'Objet.créer. Voici une méthode:-

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}

Cela maintient Crockford prototypes de l'héritage, et vérifie également pour toute méthode init de l'objet, puis l'exécute avec votre paramètre(s), comme, disons, l'homme nouveau('Jean','Dupont'). Votre code devient alors:-

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();

Alors, bob hérite de la méthode sayHello et a maintenant propres propriétés id=1 et nom='Bob'. Ces propriétés sont à la fois l'écriture et énumérable de cours. C'est aussi un moyen beaucoup plus simple pour initialiser que pour l'ECMA Objet.créer surtout si vous n'êtes pas préoccupé par l'écriture, la énumérable et attributs configurables.

Pour l'initialisation sans une méthode init suivantes Crockford mod pourrait être utilisé:-

Object.gen = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

Cela remplit le userB propres propriétés, dans l'ordre qu'ils sont définis à l'aide de l'Objet.gen paramètres à partir de la gauche vers la droite après la userB paramètre. Il utilise le pour(prop o) boucle afin que, par l'ECMA normes, l'ordre de la propriété énumération ne peut pas être garanti le même que l'ordre de définition de propriété. Cependant, plusieurs exemples de code testé sur (4) les principaux navigateurs montrer qu'ils sont les mêmes, à condition que le hasOwnProperty filtre est utilisé, et parfois, même si ce n'.

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}};  // For example

var userB = {
   name: null,
   id: null,
   sayHello: function() {
      console.log('Hello '+ this.name);
   }
}

var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());

Un peu plus simple, je dirais que l'Objet.en construction depuis userB n'a pas besoin d'une méthode init. Aussi userB n'est pas spécifiquement un constructeur, mais ressemble à un objet singleton. Donc, avec cette méthode, vous pouvez construire et l'initialisation de la normale objets simples.

14voto

samfrances Points 670

Vous pouvez rendre la méthode init return this , puis enchaîner les appels, comme ceci:

 var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
        return this;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};

var bob = Object.create(userB).init('Bob');
 

10voto

basos Points 165

Une autre utilisation possible de l'Objet.créer est pour cloner des objets immuables dans un moyen économique et efficace.

var anObj = {
    a: "test",
    b: "jest"
};

var bObj = Object.create(anObj);

bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj

// now bObj is {a: test, b: gone, c: brand}

Note: L'extrait ci-dessus crée un clone d'un objet source (aka pas une référence, comme dans cObj = aObj). Il bénéficie de plus de la copie-propriétés de la méthode (voir 1), en ce qu'elle ne copie pas l'objet des propriétés de membre. Plutôt il en crée une autre destination - objet à prototype d'ensemble sur l'objet source. En outre, lorsque les propriétés sont modifiées sur la destination de l'objet, ils sont créés "à la volée", en masquant le prototype (src) propriétés.Ceci constitue un vite un moyen efficace de clonage des objets immuables.

L'inconvénient ici est que cela s'applique à des objets source ne doit pas être modifié après la création (immuable). Si l'objet source est modifié après la création, tout le clone est démasqué propriétés seront modifiés, trop.

Violon ici(http://jsfiddle.net/y5b5q/1/) (les besoins de l'Objet.créer capable de navigateur).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X