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
À l'ère ES6, nos méthodes de création d'objets ont augmenté, et dans différents scénarios Ensuite, nous pouvons choisir différentes méthodes de construction. 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.
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 prennent toutes en charge l'implémentation de variables privées dans la fonction 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 les classes et les 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é
Par. 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('Vroom!'); // } // } // const AutoMaker = { Car }; // 工厂函数改变的实现: const AutoMaker = { Car (bundle) { return Object.create(this.bundle[bundle]); }, bundle: { premium: { drive () { console.log('Vrooom!'); }, getOptions: function () { return ['leather', 'wood', 'pearl']; } } } }; // 期望中的用法是: const newCar = AutoMaker.Car('premium'); newCar.drive(); // 'Vrooom!' // 但是因为他是一个库 // 许多地方依然这样用: const oldCar = new AutoMaker.Car(); // 如此就会导致: // TypeError: Cannot read property 'undefined' of // undefined at new AutoMaker.Car
Dans l'exemple ci-dessus, on commence par une classe et enfin on la convertit Remplacez-le par 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 dans 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: 'a'}; 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 de manière diversifiée 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 mènera sur 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 sur le mauvais chemin. 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.
Ce qui précède est ce que j'ai compilé pour vous. J'espère que cela vous sera utile à l'avenir.
Articles connexes :
Comment implémenter la fonction de communication websocket dans nodejs
Comment implémenter des graffitis dans l'applet WeChat
Explication détaillée de la façon d'utiliser les composants parents "en dehors" des composants React
Explication détaillée du protocole itérable dans la syntaxe ES6
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!