Maison  >  Article  >  interface Web  >  Explication détaillée des fonctions de classe, de constructeur et d'usine en Javascript

Explication détaillée des fonctions de classe, de constructeur et d'usine en Javascript

小云云
小云云original
2017-12-21 14:40:411927parcourir

À l'ère ES6, nos méthodes de création d'objets ont augmenté. Nous pouvons choisir différentes méthodes pour les créer dans différents scénarios. Il existe actuellement trois manières principales de créer des objets : le mot-clé class, le constructeur et la fonction factory. Ce sont tous des moyens de créer des objets, mais ils sont différents lors du développement, il faut également choisir en fonction de ces différences. Cet article présente principalement l'explication détaillée des classes, des constructeurs et des fonctions d'usine en Javascript. Les amis qui en ont besoin peuvent s'y référer. J'espère que cela pourra aider tout le monde.

Tout d'abord, regardons à quoi ressemblent ces trois méthodes


// class 关键字,ES6新特性
class ClassCar {
 drive () {
  console.log('Vroom!');
 }
}
const car1 = new ClassCar();
console.log(car1.drive());
// 构造函数
function ConstructorCar () {}
ConstructorCar.prototype.drive = function () {
 console.log('Vroom!');
};
const car2 = new ConstructorCar();
console.log(car2.drive());
// 工厂函数
const proto = {
 drive () {
  console.log('Vroom!');
 }
};
function factoryCar () {
 return Object.create(proto);
}
const car3 = factoryCar();
console.log(car3.drive());

Ces méthodes sont toutes basées sur la création de prototypes et sont prises en charge dans Implémentation de variables privées dans les fonctions constructeur. En d’autres termes, ces fonctions ont pour la plupart les mêmes caractéristiques et sont même équivalentes dans de nombreux scénarios.

En Javascript, chaque fonction peut renvoyer un nouvel objet. Lorsqu’il ne s’agit pas d’un constructeur ou d’une classe, on parle de fonction d’usine.

Les classes ES6 sont en fait du sucre de syntaxe pour les constructeurs (du moins c'est ainsi qu'elles sont implémentées à ce stade), donc tout ce qui est discuté ensuite s'applique aux constructeurs et aux classes ES6 :


class Foo {}
console.log(typeof Foo); // function

Les avantages des constructeurs et des classes ES6

  • La plupart des livres vous apprendront à utiliser des classes et des constructeurs

  • 'this' pointe vers le nouvel objet.

  • Certaines personnes aiment la lisibilité du nouveau mot-clé

  • Il peut y avoir quelques petits détails, mais s'il n'y a pas de problèmes lors du développement processus, ne vous inquiétez pas trop.

Inconvénients des constructeurs et des classes ES6

1 Vous avez besoin du nouveau mot-clé

<.>Dans ES6, les constructeurs et les classes doivent avoir le nouveau mot-clé.


function Foo() {
 if (!(this instanceof Foo)) { return new Foo(); }
}
Dans ES6, si vous essayez d'appeler une fonction de classe sans le nouveau mot-clé, une tâche sera lancée. Si vous en voulez un sans le nouveau mot-clé, vous ne pouvez utiliser qu'une fonction d'usine pour l'envelopper.

2. Les détails pendant le processus d'instanciation sont exposés à l'API externe

Tous les appels sont étroitement liés à l'implémentation du constructeur Si vous devez apporter vous-même certaines modifications pendant le processus de construction. et les pieds, c'est une chose très gênante.

3. Le constructeur ne respecte pas la règle Ouvert/Fermé

En raison du traitement détaillé du nouveau mot-clé, le constructeur viole la règle Ouvert/Fermé : l'API doit être ouverte pour expansion et éviter toute modification.

Je me suis demandé un jour que les classes et les fonctions d'usine soient si similaires, la mise à niveau de la fonction de classe vers une fonction d'usine n'aura aucun impact, mais en JavaScript, cela a un impact.

Si vous commencez à écrire des constructeurs ou des classes, mais au fur et à mesure que vous continuez, vous constatez que vous avez besoin de la flexibilité de la fonction d'usine. À ce stade, vous ne pouvez pas simplement modifier la fonction et vous en aller.

Malheureusement, vous êtes un programmeur JavaScript, et transformer un constructeur en fonction factory est une opération majeure :


// 原来的实现:
// class Car {
//  drive () {
//   console.log(&#39;Vroom!&#39;);
//  }
// }
// const AutoMaker = { Car };
// 工厂函数改变的实现:
const AutoMaker = {
 Car (bundle) {
  return Object.create(this.bundle[bundle]);
 },
 bundle: {
  premium: {
   drive () {
    console.log(&#39;Vrooom!&#39;);
   },
   getOptions: function () {
    return [&#39;leather&#39;, &#39;wood&#39;, &#39;pearl&#39;];
   }
  }
 }
};
// 期望中的用法是:
const newCar = AutoMaker.Car(&#39;premium&#39;);
newCar.drive(); // &#39;Vrooom!&#39;
// 但是因为他是一个库
// 许多地方依然这样用:
const oldCar = new AutoMaker.Car();
// 如此就会导致:
// TypeError: Cannot read property &#39;undefined&#39; of
// undefined at new AutoMaker.Car
Dans l'exemple ci-dessus, Nous commençons par une classe et enfin la transformons en une fonction d'usine capable de créer des objets basés sur un prototype spécifique. Une telle fonction peut être largement utilisée pour l'abstraction d'interface et la personnalisation de besoins spéciaux.

4. Utilisez des constructeurs pour donner une instance d'une opportunité

La différence entre les constructeurs et les fonctions d'usine est l'opérateur instanceof De nombreuses personnes utilisent instanceof pour garantir l'exactitude de leur code. Mais pour être honnête, c'est très problématique et il est recommandé d'éviter d'utiliser instanceof.

instanceof peut mentir.


// instanceof 是一个原型链检查
// 不是一个类型检查
// 这意味着这个检查是取决于执行上下文的,
// 当原型被动态的重新关联,
// 你就会得到这样令人费解的情况
function foo() {}
const bar = { a: &#39;a&#39;};
foo.prototype = bar;
// bar是一个foo的实例吗,显示不是
console.log(bar instanceof foo); // false
// 上面我们看到了,他的确不是一个foo实例
// baz 显然也不是一个foo的实例,对吧?
const baz = Object.create(bar);
// ...不对.
console.log(baz instanceof foo); // true. oops.
instanceof ne vérifie pas comme les autres langages fortement typés, il vérifie simplement l'objet sur la chaîne de prototypes.

Dans certains contextes d'exécution, il sera invalide, comme lorsque vous modifiez Constructor.prototype.

Un autre exemple est que vous commencez avec un constructeur ou une classe, puis vous l'étendez dans un autre objet, tout comme la situation ci-dessus de sa réécriture dans une fonction d'usine. À ce moment-là, instanceof aura également des problèmes.

Dans l'ensemble, instanceof est un autre grand changement dans les appels de fonctions de constructeur et d'usine.

Avantages de l'utilisation des classes

  • Un mot-clé pratique et autonome


  • Le seul moyen faisant autorité pour implémenter des classes en JavaScript.


  • C'est une bonne expérience pour les autres développeurs qui ont de l'expérience dans le développement de langages de classe.

Inconvénients de l'utilisation des classes

Tous les inconvénients des constructeurs, plus :

Utiliser le mot-clé extends pour créer une classe problématique pour les utilisateurs C'est un gros tentation.

L'héritage hiérarchique des classes entraînera de nombreux problèmes bien connus, notamment la classe de base fragmentée (la classe de base sera détruite en raison de l'héritage), le problème de la banane gorille (objets mélangés à des contextes complexes), la duplication par nécessité (les classes sont héritées diversifiés doivent être modifiés de temps en temps) et ainsi de suite.

Bien que les deux autres méthodes puissent également vous poser ces problèmes, lorsque vous utilisez le mot-clé extend, l'environnement vous guidera dans cette voie. En d’autres termes, cela vous amène à écrire du code avec des relations inflexibles, plutôt qu’à écrire du code plus réutilisable.

Avantages de l'utilisation des fonctions d'usine

Les fonctions d'usine sont plus flexibles que les classes et les constructeurs et ne conduiront pas les gens à des erreurs. Cela ne vous coincera pas non plus dans une profonde chaîne d’héritage. Vous pouvez utiliser de nombreuses méthodes pour simuler l'héritage

1. Renvoyez n'importe quel objet avec n'importe quel prototype

Par exemple, vous pouvez créer différentes instances d'un lecteur multimédia via la même implémentation. Des instances peuvent être créées pour différents les formats multimédias, utilisant différentes API, ou une bibliothèque d'événements peuvent être destinés aux événements DOM ou aux événements ws.

La fonction factory peut également instancier des objets via le contexte d'exécution, qui peut bénéficier du pool d'objets et d'un modèle d'héritage plus flexible.

2. Ne vous inquiétez pas d'un refactoring complexe

Vous n'aurez jamais besoin de convertir les fonctions d'usine en constructeurs, le refactoring n'est donc pas nécessaire.

3. Pas de nouveau

Vous n'utilisez pas le mot-clé new pour créer un nouvel objet, vous pouvez maîtriser ce processus vous-même.

4. Standardisez ce comportement

C'est celui que vous connaissez et vous pouvez l'utiliser pour obtenir l'objet parent. Par exemple, dans player.create(), cela pointe vers le joueur, et d'autres peuvent également être liés via un appel et une application.

5. Aucun problème avec instanceof

6. Certaines personnes aiment la lisibilité et l'intuitivité de l'écriture directe sans nouveauté.

Inconvénients des fonctions d'usine

  • ne gère pas automatiquement les prototypes, et les prototypes de fonctions d'usine n'affecteront pas la chaîne de prototypes .

  • cela ne pointe pas automatiquement vers le nouvel objet dans la fonction d'usine.

  • Il peut y avoir quelques petites différences dans les détails, mais s'il n'y a aucun problème pendant le processus de développement, ne vous inquiétez pas trop.

Conclusion

À mon avis, la classe est peut-être un mot clé pratique, mais elle ne peut pas le cacher Conduira sans méfiance utilisateurs dans le gouffre de l’héritage. Un autre risque est la possibilité qu’à l’avenir vous souhaitiez utiliser les fonctions d’usine et que vous deviez procéder à des changements très importants.

Si vous travaillez dans une équipe relativement nombreuse, si vous souhaitez modifier une API publique, vous risquez d'interférer avec du code auquel vous n'avez pas accès, vous ne pouvez donc pas fermer les yeux sur l'impact des fonctions modifiées. .

L'un des avantages du modèle d'usine est qu'il est non seulement plus puissant et plus flexible, mais qu'il encourage également toute l'équipe à rendre l'API plus simple, plus sûre et plus légère.

Recommandations associées :

Introduction détaillée à ceci et retour dans les constructeurs JavaScript

Comment utiliser le modèle d'usine et le constructeur dans JavaScript pour créer des objets ?

Exemples détaillés de la différence entre les littéraux de fonction javascript et les constructeurs Function()

Comment utiliser le mode usine, le mode constructeur et le mode prototype dans javascript Explication détaillée de la création d'instances d'objet

Explication détaillée des expressions et des constructeurs dans le didacticiel JavaScript de base

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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