Maison  >  Article  >  interface Web  >  Modèles de création d'objets JavaScript et bonnes pratiques

Modèles de création d'objets JavaScript et bonnes pratiques

黄舟
黄舟original
2017-02-23 13:48:31923parcourir

"Créer des objets" en JavaScript est un sujet complexe. Ce langage offre de nombreuses façons de créer des objets, et les débutants comme les utilisateurs expérimentés peuvent ne pas savoir laquelle choisir. Cependant, bien qu'il existe de nombreuses façons de créer des objets et que la syntaxe puisse sembler très différente, elles peuvent en réalité être plus similaires que vous ne le pensez. Cet article vous fera découvrir les méthodes de création d'objets, révélant les dépendances et les relations progressives entre les différentes méthodes.

Littéraux d'objets

Notre premier arrêt est sans aucun doute le moyen le plus simple de créer des objets, des littéraux d'objets. JavaScript prêche toujours qu'il peut créer des objets "à partir de rien" - pas de classes, pas de modèles, pas de prototypes - et "pop", un objet avec des méthodes et des données apparaît.

var o = {
  x: 42,
  y: 3.14,
  f: function() {},
  g: function() {}
};

Mais cette méthode a un inconvénient : si on veut créer un objet du même type ailleurs, il faut copier et coller les méthodes, les données et l'initialisation de cet objet. Nous avons besoin d’un moyen de créer des objets du même type par lots au lieu d’un seul.

Fonction d'usine

Notre prochain arrêt est la fonction d'usine. Évidemment, il est plus simple d’utiliser cette méthode pour créer une classe d’objets avec la même structure, interface et implémentation. Nous ne créons pas directement un littéral d'objet, mais utilisons le littéral d'objet comme valeur de retour de la fonction. Lorsque nous devons créer des objets du même type plusieurs fois ou à plusieurs endroits, il nous suffit d'appeler cette fonction.

function thing() {
  return {
    x: 42,
    y: 3.14,
    f: function() {},
    g: function() {}
  };
}

var o = thing();

Mais cette approche a aussi un inconvénient : elle entraînera une extension de mémoire, car chaque objet contient une copie indépendante de la fonction d'usine. En théorie, nous voulons que tous les objets partagent une copie de la fonction d'usine.

Prototype Chain

JavaScript fournit un mécanisme intégré pour partager des données entre objets, appelé chaîne de prototypes. Lorsque nous accédons à la propriété d'un objet, il délègue à un autre objet pour compléter la demande. Nous pouvons utiliser cela pour modifier la fonction d'usine afin que chaque objet qu'elle crée contienne uniquement ses propres données uniques, tandis que les demandes d'autres propriétés sont toutes déléguées à un objet commun sur la chaîne de prototypes.

var thingPrototype = {
  f: function() {},
  g: function() {}
};

function thing() {
  var o = Object.create(thingPrototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

En fait, JavaScript lui-même possède des mécanismes intégrés pour prendre en charge ce modèle commun. Nous n'avons pas besoin de créer nous-mêmes cet objet partagé (c'est-à-dire l'objet prototype). JavaScript créera automatiquement un objet prototype pour chaque fonction. Nous pouvons mettre les données partagées directement dans cet objet.

thing.prototype.f = function() {};
thing.prototype.g = function() {};

function thing() {
  var o = Object.create(thing.prototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

Mais cette méthode présente aussi un inconvénient : elle entraînera des doublons. Les première et dernière lignes de la fonction chose ci-dessus sont répétées dans chaque "fonction d'usine du prototype délégué", avec presque aucune différence.

Classes ES5

Nous pouvons extraire ces codes répétitifs et les mettre dans une fonction personnalisée. Cette fonction créera un objet et établira une relation de délégation (héritage) avec le prototype d'une autre fonction arbitraire (fonction paramètre). Ensuite, nous utilisons l'objet nouvellement créé comme paramètre, appelons cette fonction (fonction paramètre) et finalement renvoyons-le. nouvel objet.

function create(fn) {
  var o = Object.create(fn.prototype);

  fn.call(o);

  return o;
}

// ...

Thing.prototype.f = function() {};
Thing.prototype.g = function() {};

function Thing() {
  this.x = 42;
  this.y = 3.14;
}

var o = create(Thing);

En fait, JavaScript prend également en charge cette méthode. La fonction create que nous avons définie est en fait une implémentation de base du mot-clé new, nous pouvons donc facilement remplacer create par new.

Thing.prototype.f = function() {};
Thing.prototype.g = function() {};

function Thing() {
  this.x = 42;
  this.y = 3.14;
}

var o = new Thing();

La station à laquelle nous sommes arrivés est souvent appelée la classe ES5. Il crée des objets via des fonctions, délègue les données qui doivent être partagées à des objets prototypes et utilise le nouveau mot-clé pour gérer la logique répétée.

Mais cette méthode a aussi un inconvénient : elle est verbeuse et moche, et elle le sera encore plus lors de l'implémentation de l'héritage.

ES6 类

JavaScript最新的相关改进是ES6 类,用新语法来实现上述功能要简洁得多。

class Thing {
  constructor() {
    this.x = 42;
    this.y = 3.14;
  }

  f() {}
  g() {}
}

var o = new Thing();

比较

多年以来,JavaScript开发者们与原型链的关系总是若即若离,纠缠不清。而今天我们最有可能遇到的两种创建对象的方式,一种是强烈依赖原型链的class语法,另一种则是完全不依赖原型链的工厂函数语法。这两种方式在性能上和特点上是不一样的——尽管差别不太大。

性能

今天的JavaScript引擎已经经过了大幅度的优化,以至于很难通过JavaScript代码来推断怎样会比较快。关键在于测量方法。然而测量方法有时也会失灵。通常每六周就会有更新的JavaScript引擎发布,而在这之前采取的测量方法,和基于这种测量方法做出的决策都有可能失去意义。因此,我的经验法则是选择最官方、最广泛使用的语法,因为大多数时候它经历的实践检验最多,因而性能是最高的。目前来说class语法最符合这一点,在我写这篇文章时,class语法大约比返回字面量的工厂函数快3倍。

特点

随着ES6的发布,类与工厂函数之间曾经存在的几点差异消失了。现在,工厂函数和类都能够强制实现真正的私有数据——工厂函数通过闭包实现,类通过WeakMap实现。两者都能实现多重继承——工厂函数可以将其他属性混入自己的对象,类也可以将其他属性混入自己的原型,或者通过类工厂,通过代理也能实现。工厂函数和类也都可以在需要的时候返回任意对象,语法也都很简单。

结论

综合考虑,我更倾向于class语法。它标准、简单、干净、快速,还提供了所有曾经只有函数工厂才具备的特点。

 以上就是JavaScript 创建对象模式与最佳实践的内容,更多相关内容请关注PHP中文网(www.php.cn)! 


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn