Je crois qu'au niveau POO, chacun à ses petites préférences, voici les miennes. Depuis la sortie d'ES5, l'héritage simple est très facile et réel (instanceof).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 var Animal = function( name ){ this.name = name; }, Dog = function( name, pays ){ Animal.call( this, name ); }; Animal.prototype = { "sayName" : function(){ return this.name; }, "race" : "indéterminée" }; // Héritage simple uniquement Dog.prototype = Object.create( Animal.prototype ); // Surcharge de la méthode sayName Dog.prototype.sayName = function( str ){ return ( str + Animal.prototype.sayName.call( this ) ); }; Dog.prototype.bark = function(){ return "Woof!"; }; var MonChien = new Dog( "Youki", "Belgique" ), AutreChien = new Dog( "Caline", "France" ); AutreChien.race = "Bichon"; console.log( "MonChien.sayName() = ", MonChien.sayName( "Mon joli toutou s'appelle " ) ); console.log( "MonChien.bark() = ", MonChien.bark() ); console.log( "MonChien : ", MonChien ); console.log( "MonChien instanceof Dog : ", MonChien instanceof Dog ); console.log( "MonChien instanceof Animal : ", MonChien instanceof Animal ); console.log( "AutreChien.race : ", AutreChien.race ); console.log( "MonChien.race : ", MonChien.race ); console.log( "AutreChien.sayName() : ", AutreChien.sayName( "Mon joli toutou s'appelle " ) ); console.log( "AutreChien.bark() : ", AutreChien.bark() ); /* * On peut ajouter des propriétés à un objet existant */ Object.defineProperties( AutreChien, { "vacciner" : { "value" : true, "enumerable" : true } }); console.log( "vacciner : ", AutreChien.vacciner, MonChien.vacciner ); console.log( "MonChien keys : ", Object.keys( MonChien ) ); console.log( "AutreChien keys : ", Object.keys( AutreChien ) );***************
Au niveau de la construction des objets ES5, c'est très pratique, mais il y a des pièges, il n'y a pas d'héritage d'objets. Ma préférence va au clonage et à l'extension des objets ES5.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 var Animal = Object.create( {}, { "_nomAnimal": { "value" : "", "writable" : true, "configurable" : true }, "nomAnimal" : { "get" : function(){ return this._nomAnimal; }, "set" : function( value ){ this._nomAnimal = value; }, "enumerable" : true, "configurable" : true } }), Pays = Object.create( {}, { "_nomPays": { "value" : "", "writable" : true, "configurable" : true }, "nomPays" : { "get" : function(){ return this._nomPays; }, "set" : function( value ){ this._nomPays = value; }, "enumerable" : true, "configurable" : true } }), Dog = Object.dvjhExtendAndProperties( Animal, Pays, { "sayNameDog" : { "value" : function( str ){ return str + this.nomAnimal; }, "enumerable" : true, "configurable" : true }, "IdDog" : { "value" : function(){ return this.nomAnimal + this.nomPays; }, "enumerable" : true, "configurable" : true } }), Youki = Object.dvjhClone( Dog ), Caline = Object.dvjhClone( Dog ); Youki.nomAnimal = "Youki"; Youki.nomPays = "Belgique"; console.log( "Youki : ", Object.keys( Youki ), Object.getOwnPropertyNames( Youki ) ); console.log( "IdDog : ", Object.getOwnPropertyDescriptor( Youki, "IdDog" ) ); console.log( Youki.sayNameDog( "C'est " ) ); console.log( Youki.nomPays ); console.log( Youki.IdDog() ); Caline.nomAnimal = "Caline"; Caline.nomPays = "France"; console.log( "Caline : ", Object.keys( Caline ), Object.getOwnPropertyNames( Caline ) ); console.log( "nomAnimal : ", Object.getOwnPropertyDescriptor( Caline, "nomAnimal" ) ); console.log( Caline.sayNameDog( "C'est " ) ); console.log( Caline.nomPays ); console.log( Caline.IdDog() );J'avais commencé un projet de tutoriel sur le sujet au début de 2012, mais je l'ai abandonné pour cause de maladie et puis à cause d'ES6 qui, grâce à du sucre syntaxique, permets aux habitués des langages-objets de faire de la POO classique à base de classes. J'ai testé, quoi qu'on en pense, c'est très pratique pour les habitués de la POO. Mais la sortie du draft ES6 prend de plus en plus de retard, au mieux il faudra attendre le premier trimestre 2014.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 /* * var ObjFinal = Object.dvjhClone( Obj ); * Retourne ObjFinal ou null en cas d'échec. * * Crée un nouvel objet à partir du prototype d'Obj, * puis lui ajoute les propriétés d'Obj. * * Object.dvjhCloneAndProperties( Obj, PropertiesObj ); * * Crée un nouvel objet à partir du prototype d'Obj, * puis lui ajoute les propriétés d'Obj, puis lui * ajoute les propriétés contenues dans PropertiesObj. * * var ObjFinal = Object.dvjhExtend( Obj1, Obj2 [, ... , ObjN] ); * Retourne ObjFinal ou null en cas d'échec. * L'ordre des objets ObjX détermine le contenu de l'objet ObjFinal. * * Crée un dvjhClone d'Obj1 et lui ajoute les propriétés * des objets suivants. * * Les causes d'échec peuvent être multiples. * * L'erreur la plus fréquente résulte du fait que deux * objets possèdent une clé identique et que la propriété * correspondant à cette clé est non configurable dans * l'objet étendu. * * Pour deux clés identiques, la première étant configurable, * c'est le contenu de la propriété d'ObjX+1 qui remplace celle * de ObjX. * * Object.dvjhExtendAndProperties( Obj1, ..., ObjN, PropertiesObj ); * * Crée un dvjhClone d'Obj1 et lui ajoute les propriétés * des objets suivants, puis lui ajoute les propriétés contenues * dans PropertiesObj. */ Object.defineProperties( Object, { "dvjhClone" : { "value" : function( Obj ){ var NouvelObjet = null; if ( typeof Obj === "object" ){ try { NouvelObjet = Object.create( Object.getPrototypeOf( Obj ) ); Object.getOwnPropertyNames( Obj ).forEach( function( key ){ Object.defineProperty( NouvelObjet, key, Object.getOwnPropertyDescriptor( Obj, key ) ); }); } catch( evt ){ return null; } } return NouvelObjet; }, "enumerable" : true }, "dvjhCloneAndProperties" : { "value" : function( Obj, Props ){ var NouvelObjet = Object.dvjhClone( Obj ); if ( NouvelObjet && typeof Props === "object" ){ try { Object.defineProperties( NouvelObjet, Props ); } catch( evt ){ return null; } } return NouvelObjet; }, "enumerable" : true }, "dvjhExtend" : { "value" : function(){ var args = Array.prototype.slice.call( arguments ), Obj1 = args.shift(), Obj2 = null, NouvelObjet = null; if ( args.length > 0 && typeof Obj1 === "object" ){ NouvelObjet = Object.dvjhClone( Obj1 ); } else { return null; } while( args.length > 0 ){ Obj2 = args.shift(); if ( typeof Obj2 === "object" ){ try { Object.getOwnPropertyNames( Obj2 ).forEach( function( key ){ Object.defineProperty( NouvelObjet, key, Object.getOwnPropertyDescriptor( Obj2, key ) ); }); } catch( evt ){ return null; } } } return NouvelObjet; }, "enumerable" : true }, "dvjhExtendAndProperties" : { "value" : function(){ var args = Array.prototype.slice.call( arguments ), Props = args.pop(), Obj1 = args.shift(), Obj2 = null, NouvelObjet = null; if ( args.length > 0 && typeof Obj1 === "object" ){ NouvelObjet = Object.dvjhClone( Obj1 ); } else { return null; } while( args.length > 0 ){ Obj2 = args.shift(); if ( typeof Obj2 === "object" ){ try { Object.getOwnPropertyNames( Obj2 ).forEach( function( key ){ Object.defineProperty( NouvelObjet, key, Object.getOwnPropertyDescriptor( Obj2, key ) ); }); } catch( evt ){ return null; } } } if ( NouvelObjet && typeof Props === "object" ){ try { Object.defineProperties( NouvelObjet, Props ); } catch( evt ){ return null; } } return NouvelObjet; }, "enumerable" : true } });
Partager