Construction d'un modèle de type dans le but d'améliorer la gestion des propriétés d'un objet
par
, 23/11/2014 à 00h33 (1781 Affichages)
Dans le billet précédent, nous avons vu comment recueillir la valeur de la propriété [[Class]] avec la fonction getType().
Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 function getType( Obj ){ return Object.prototype.toString.call( Obj ).match( /\s([a-zA-Z]+)/ )[ 1 ].toLowerCase(); }
Pour vérifier le typage des propriétés d'un objet on peut utiliser un objet englobant (proxy), mais l'API Proxy sera au mieux disponible en ES6. De plus, la technique du proxy à la réputation d'être difficile à mettre au point pour couvrir tous les cas d'utilisation et de modification d'un objet, certains auteurs signalent aussi des pertes de mémoire.
Nous allons utiliser une technique moins exaltante, mais plus sûre et utilisable en ES5.
La fonction setModel
Code JavaScript : 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 function setModel( Obj ){ if ( getType( Obj ) === "object" ){ Obj[ "_objectModel" ] = Object.create( Object.prototype ); Object.getOwnPropertyNames( Obj ).forEach( function( key ){ if ( key != "_objectModel" ) { Object.defineProperty( Obj[ "_objectModel" ], key, { "value" : getType( Obj[ key ] ), "enumerable" : true }); } }); } else { throw "Erreur dans setModel(), " + Obj + " n'est pas un objet"; } }
Cette fonction ajoute simplement une propriété "_objectModel" à un objet "source". La valeur de cette propriété est un objet qui contient le type des propriétés de l'objet "source".
La méthode doit être appelée directement après la construction d'un objet et elle peut être appelée après chaque ajout de propriétés.
Les exemples d'utilisation vous aideront à y voir plus clair.
Exemple simpliste
Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 var Personne = {}; Personne.nom = "Daniel"; setModel( Personne ); console.log( Personne ); /* * nom: "Daniel" * _objectModel: * nom: "string" */
Exemple d'un objet JSON
Code JavaScript : 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 /* * Définition de l'objet Animal. * * On peut utiliser this._objectModel dans * le mutateur (set) mais n'oublier d'appeler * setModel( Animal ) sous peine d'erreur * lors de l'utilisation de l'objet. */ var Animal = Object.create( Object.prototype, { "_nomAnimal": { "value" : "", "writable" : true, "configurable" : true }, "nomAnimal" : { "get" : function(){ return this._nomAnimal; }, "set" : function( value ){ if ( this._objectModel._nomAnimal === getType( value ) ) { this._nomAnimal = value; } }, "enumerable" : true, "configurable" : true } }); setModel( Animal ); Animal.nomAnimal = "Makita"; console.log( Animal ); /* * _nomAnimal: "Makita" * nomAnimal: (...) get set * _objectModel: * _nomAnimal: "string * "nomAnimal: "string" */
Exemple d'héritage avec ajout d'un accesseur (get) et d'un mutateur (set)
Code JavaScript : 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 /* * Construction des fonctions */ var Animal = function( name ){ this._name = name; }, Dog = function( name, pays ){ Animal.call( this, name ); this._pays = pays; }; /* * Construction du prototype d'Animal */ Animal.prototype = { "sayName" : function() { return this._name; } }; /* * Héritage */ Dog.prototype = Object.create( Animal.prototype ); /* * Ajout de propriétés */ Dog.prototype.sayName = function( str ){ var texte = str || ""; return ( texte + Animal.prototype.sayName.call( this ) ); }; Dog.prototype.bark = function(){ return "Woof!"; }; /* * Construction des objets */ var MonChien = new Dog( "Youki", "Belgique" ), AutreChien = new Dog( "Caline", "France" ); /* * Ajout du modèle de type */ setModel( MonChien ); setModel( AutreChien ); /* * Ajout de la propriété "vacciner" */ Object.defineProperties( AutreChien, { "vacciner" : { "value" : true, "enumerable" : true } }); /* * Reconstruction du modèle de type * * Inutile, vu l'ajout suivant, mais * montre que la multiplicité des appels * est possible. */ setModel( AutreChien ); /* * Ajout d'un accesseur et d'un mutateur */ Object.defineProperty( AutreChien, "name", { "get" : function( ){ return this._name; }, "set" : function( value ) { if ( this._objectModel._name === getType( value ) ) { this._name = value; } }, "enumerable" : true, "configurable" : true }); /* * Reconstruction du modèle de type */ setModel( AutreChien ); /* * Utilisation du mutateur */ AutreChien.name = "Elliot"; console.log( AutreChien ); /* * _name: "Elliot" * _pays: "France" * vacciner: true * name: (...) get set * _objectModel: { * _name: "string" * name: "string" * _pays: "string" * vacciner: "boolean" */