Classes JavaScript
Je comprends le code JavaScript de base des pseudo-classes:
function Foo(bar) {
this._bar = bar;
}
Foo.prototype.getBar = function() {
return this._bar;
};
var foo = new Foo('bar');
alert(foo.getBar()); //'bar'
alert(foo._bar); //'bar'
Je comprends également que le motif de module, qui peut émuler l'encapsulation:
var Foo = (function() {
var _bar;
return {
getBar: function() {
return _bar;
},
setBar: function(bar) {
_bar = bar;
}
};
})();
Foo.setBar('bar');
alert(Foo.getBar()); //'bar'
alert(Foo._bar); //undefined
Mais il ya de l'onu-programmation orientée objet-comme les propriétés de ces deux modèles. Le premier n'a pas de fournir de l'encapsulation. Ce dernier ne fournit pas d'instanciation. Les deux modèles peuvent être modifiés à l'appui de pseudo-héritage.
Ce que je voudrais savoir c'est si il n'y a aucun motif qui permet de:
- Héritage
- Encapsulation (soutien pour le "privé" propriétés/méthodes)
- L'instanciation (peut avoir plusieurs instances de la "classe", chacun avec son propre état)
- Avez-vous passé en revue une partie de la ces articles?
- Oui, j'ai un dossier de signets avec des dizaines de la programmation orientée objet JS articles. J'ai lu Crockford, Resig, Osmani, et beaucoup d'autres mieux que moi JS développeurs avis sur la question.
- Certains frameworks JS comme le Prototype de fournir un soutien accru pour la création de classes. prototypejs.org/learn/class-inheritance
- Je me souviens avoir vu des réponses relatives à ce pour des questions sur la façon de créer des "protégés", les variables/méthodes en Javascript. Je n'en trouve pas pour le moment, mais vous pourriez avoir plus de chance à la recherche pour ce terme. (Je vous conseille de ne pas essayer de si dur, ça devient vraiment compliqué et pas idiomatiques)
- Je discuter de certains de ces modèles de la façon de traiter cette question dans mon blog. S'il vous plaît vérifier: ncombo.wordpress.com/2012/12/30/...
- Vous pourriez être intéressé à la Machine, ou plus précisément le code qu'il produit lors de la compilation de ses classes en valide JS. Tous les vrais typage à la compilation, mais il produit des prototypes qui se comportent tout à fait comme les classes traditionnelles.
- Si vous êtes à la recherche pour les échantillons de code pour imiter de la programmation orientée objet des comportements similaires à des langages de programmation comme java en JavaScript, Checkout Classe JavaScript ici.
Vous devez vous connecter pour publier un commentaire.
quoi à ce sujet :
Et maintenant, nous avons l'instanciation, l'encapsulation et l'héritage.
Mais, il y a toujours un problème. Le
private
variable eststatic
parce qu'il est partagé entre toutes les instances deFoo
. Démonstration rapide :Une meilleure approche pourrait être à l'aide de conventions pour les variables privées : toute variable privée doit commencer par un caractère de soulignement. Cette convention est bien connu et largement utilisé, de sorte que quand un autre programmeur utilise ou modifie votre code et voit une variable de départ avec un trait de soulignement, qu'il sache que c'est privé, pour un usage interne seulement et il ne sera pas le modifier.
Voici la réécriture à l'aide de la présente convention :
Maintenant, nous avons l'instanciation, héritage, mais nous avons perdu notre encapsulation en faveur de conventions :
mais le privé vars sont accessibles :
_bar
variable ici, est partagée par toutes les instances. N'hésitez pas à tester ça. Je l'ai fait.a = new Foo(); b = new Foo(); a.setBar('a'); b.setBar('b'); alert(a.getBar());
. Vous ne verrez pas "une", mais "b" au lieu de cela, parce que_bar
n'est pas unique pour chaque instance.defineProperty
(goo.gl/uH7rQk) et en utilisant les getters et les setters n'est pas pris en charge dans IE 8 et inférieur (goo.gl/k5j0Gt). Vous devriez poster une réponse même si, de laisser quelqu'un d'autre de la visualisation de ce thread connaître les autres nouvelles moyens.Je pense que ce que vous cherchez est le "Révélateur Prototype de Modèle".
Dan Wahlin a un super blog post: http://weblogs.asp.net/dwahlin/archive/2011/08/03/techniques-strategies-and-patterns-for-structuring-javascript-code-revealing-prototype-pattern.aspx
et même mieux Pluralsight cours sur ce sujet et sur d'autres JavaScript liées à des structures: http://pluralsight.com/training/courses/TableOfContents?courseName=structuring-javascript&highlight=dan-wahlin_structuring-javascript-module1!dan-wahlin_structuring-javascript-module2!dan-wahlin_structuring-javascript-module5!dan-wahlin_structuring-javascript-module4!dan-wahlin_structuring-javascript-module3#structuring-javascript-module1
Fermetures sont à votre ami!
Il suffit d'ajouter le suivant minuscule fonction de votre haut niveau de l'espace de noms et vous êtes prêt à la programmation orientée objet, complet avec
et les méthodes
La fonction ci-dessus simplement les fils jusqu'à la classe de prototype et de l'éventuelle constructeur parent, et renvoie le résultant constructeur, prêt au moment de l'instanciation.
Vous pouvez maintenant le plus naturellement déclarer vos classes de base (ie. qui s'étendent {}) dans les quelques lignes de code, compléter avec de la statique, de l'instance, publiques et privées, propriétés et méthodes:
Extension d'une classe? D'autant plus naturel que de bien:
En d'autres termes, passer le parent le constructeur de la classe à la clazz fonction et ajouter
_super.call(this, arg1, ...)
à l'enfant de la classe de constructeur, qui appelle les parents de la classe de constructeur avec les arguments requis. Comme avec n'importe quel standard de succession, le constructeur parent d'appel doit venir en premier dans l'enfant du constructeur.Noter que vous êtes libre soit explicitement le nom du constructeur avec
this.constructor = function(arg1, ...) {...}
, outhis.constructor = function MyBaseClass(arg1, ...) {...}
si vous avez besoin d'un accès simple à l'constructeur du code dans le constructeur, ou même tout simplement de retourner le constructeur avecreturn function MyBaseClass(arg1, ...) {...}
comme dans le code ci-dessus. Selon ce que vous sentez le plus à l'aise avec.Simplement d'instancier des objets de ces classes comme vous le feriez normalement à partir d'un constructeur:
myObj = new MyBaseClass();
Remarquez comment les fermetures de bien encapsuler l'ensemble de la classe fonctionnalités, y compris son prototype et constructeur, ce qui procure une espace de noms pour la statique et de l'instance, privé et public, des propriétés et des méthodes. Le code dans une classe de fermeture est complètement libre de toutes contraintes. Pas de cadre, pas de contraintes, juste un bon vieux Javascript. Les fermetures de règle!
Oh, et si vous voulez injecter singleton dépendances (par exemple. les services) dans votre classe (ie. prototype),
clazz
va le faire pour vous à la AngularJS:Que le code ci-dessus tente d'illustrer, à injecter des singletons dans une classe, il suffit de placer la classe de fermeture de la dernière entrée dans un tableau avec toutes ses dépendances. Également ajouter des paramètres correspondant à la classe de fermeture à l'avant de la
_super
paramètre et dans le même ordre que dans le tableau.clazz
permettra d'injecter les dépendances à partir du tableau comme arguments dans la classe de fermeture. Les dépendances sont alors disponibles n'importe où dans la classe de fermeture, y compris le constructeur.En fait, depuis les dépendances sont injectés dans le prototype, ils sont disponibles pour les méthodes statiques avant même que tout objet est instancié à partir de la classe. C'est très puissant pour le câblage de vos applications ou de l'unité et de bout en bout tests. Il supprime également la nécessité d'injecter des singletons dans les constructeurs, qui, autrement, inutilement clobbers le constructeur du code.
Vérifier ce violon: http://jsfiddle.net/5uzmyvdq/1/
Commentaires et suggestions bienvenus!
Javascript est certainement la POO. Vous avez toujours le polymorphisme, cependant, vous avez à sacrifier soit l'encapsulation ou d'instanciation qui est le problème que vous avez couru dans.
Essayez ceci pour juste la brosse sur vos options.
http://www.webmonkey.com/2010/02/make_oop_classes_in_javascript/
Aussi une question aussi ancienne que j'avais mis en signet:
Est JavaScript orienté objet?
Vous pouvez voir plus de ce lien Communauté Mozilla
Github
Je pensais à ce sujet récemment et les limites des différentes approches. La meilleure solution que j'ai été en mesure de venir avec est ci-dessous.
Il semble pour résoudre les problèmes de l'héritage, l'instanciation et l'ecapsulation (au moins à partir d'essais sur Google Chrome v. 24), mais probablement à un coût d'utilisation de la mémoire.
Un problème avec beaucoup de JS classes là, c'est qu'ils ne sont pas sûr de leurs champs et de méthodes qui signifie que n'importe qui de l'utiliser risquez de remplacer une méthode. Par exemple le code:
sera de sortie:
Comme vous pouvez le voir le changeName fonction est surchargée. Le code suivant les méthodes de la classe et les champs, et les getters et setters serait utilisé pour accéder à leur rendre cela plus d'un "régulier" class trouvé dans d'autres langues.
Ce sorties:
Maintenant vos méthodes de la classe ne peut pas être remplacé par des valeurs aléatoires ou des fonctions et du code dans les getters et setters toujours exécuter lors de la tentative de lecture ou d'écriture sur le terrain.
Cette fermeture permet l'instanciation et l'encapsulation, mais pas de l'héritage.