OVH Cloud OVH Cloud

Création d'objets

24 réponses
Avatar
bertrand
Bonjour,

Quelle est la meilleur façon de créer un objet :

function MyObjet()
{
this.myPropriete = 0;

this.MyMethode = function(arg)
{
alert(arg);
}
}

ou alors

function MyObjet()
{
this.myPropriete = 0;
}

MyObjet.prototype.MyMethode = function(arg)
{
this.myPropriete += arg;
alert(myPropriete);
}

Dans le deuxième cas, on ne peut ni avoir de méthode, ni de propriété
privés, tout est public.

Merci pour vos réponses,

Matt...

10 réponses

1 2 3
Avatar
Matt
Bonjour,

Je reposte un message avec un nouvel objet plus parlant et en utilisant
des prototypes...

// Constructeur Individu
var MyIndividu = function()
{
// Recuperation des donnees
if(arguments.length == 1)
this.nom = arguments[0] ;
}
// Nom
MyIndividu.prototype.nom = "";

// Affichage de l'individu
MyIndividu.prototype.affiche = function()
{
alert(""" + this.nom + """);
}

// Constructeur Agenda
var MyAgenda = function()
{
this.listeIndividu = new Array();
}
// Liste des individus
MyAgenda.prototype.listeIndividu = null;

// On enregistre un nouvel individu
MyAgenda.prototype.setIndividu = function()
{
var newIndividu = new MyIndividu(arguments[0]);
this.listeIndividu.push(newIndividu);
}
// On affiche tout les individus
MyAgenda.prototype.getAllIndividu = function()
{
for(var i = 0; i < this.listeIndividu.length; i++)
this.listeIndividu[i].affiche();
}

Voila, je voudrais donc savoir si la façon de faire ci dessus est
correct afin que je puisse refaire les quelques objets que j'ai
précédemment crée, avec cette approche.
Une question d'appellation , qu'est ce que MyAgenda ? peut on parler
d'une classe et quand on l'instancie peut on parler d'un objet.

Merci pour vos réponses,

Matt...
Avatar
Pascal
Matt a écrit :
Bonjour,



Bonjour,

// Constructeur Individu
var MyIndividu = function()
{
// Recuperation des donnees
if(arguments.length == 1)
this.nom = arguments[0] ;
}



JS est très souple au niveau du passage d'arguments, pas besoin de
s'assurer s'ils ont bien été passés.
Sauf, bien sûr, s'ils sont impliqués dans la construction de l'objet
mais, dans le cas présent, j'utiliserais plutôt un "setter" pour le n om,
donc une méthode genre "setNom(nom)", pour être cohérent avec la mé thode
"setIndividu()" définie plus bas.

// Nom
MyIndividu.prototype.nom = "";



C'est théoriquement correct, mais là je ne vois pas l'intérêt du
prototypage.

Je n'en connais que deux usages intéressants :
1. Eviter d'encombrer la mémoire dès la création d'un nouvel objet. Pour
une propriété, ça vaut le coup si elle est de type composée, et a
fortiori de type objet, mais pas scalaire comme ici.
2. Modulariser le code, ce qui va de soi pour une méthode, mais pas tro p
pour une propriété.

// Affichage de l'individu
MyIndividu.prototype.affiche = function()
{
alert(""" + this.nom + """);
}



On va dire que la méthode "alert()" est là seulement pour mettre quel que
chose.
Si c'est pour le débogage, je conseillerai plutôt "console.log()".

// Constructeur Agenda
var MyAgenda = function()
{
this.listeIndividu = new Array();
}



Pas cohérent avec l'initialisation du nom qui est une chaîne littér ale.
Donc, soit le nom est initialisé avec "new String", soit la liste est
initialisée avec "[]".

// Liste des individus
MyAgenda.prototype.listeIndividu = null;



Pourquoi prototyper, puisque la liste est définie dans le constructeur ?
Cela dit, comme c'est une liste d'objets (qui peuvent donc grossir) je
préfère cette solution, mais alors il ne faut pas la définir avant !

// On enregistre un nouvel individu
MyAgenda.prototype.setIndividu = function()
{
var newIndividu = new MyIndividu(arguments[0]);
this.listeIndividu.push(newIndividu);
}



Pareil que ma première remarque, autant passer un argument nommé à la
méthode "setIndividu(nom)".

// On affiche tout les individus
MyAgenda.prototype.getAllIndividu = function()
{
for(var i = 0; i < this.listeIndividu.length; i++)
this.listeIndividu[i].affiche();
}



Petite astuce au cas où la liste serait importante : la condition de
répétition de la boucle est évaluée avant chaque passage, donc mi eux
vaut définir une variable égale au nombre d'éléments à traiter juste
avant la boucle, ce sera plus rapide.
Par exemple :
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++) { ... }

Une question d'appellation , qu'est ce que MyAgenda ? peut on parler
d'une classe et quand on l'instancie peut on parler d'un objet.



Avec les versions 1.x, pas vraiment. La version 2 introduit la notion de
classe et d'instanciation, mais elle n'est implémentée que dans les
moteurs ActionScript.
Donc, pour les moteurs JS des clients Web, ce ne sont que des objets
primitifs que l'on copie avec le mot clé "new", d'où la notion géné rale
de prototypage associée à ce langage (cela fait partie de son paradig me).

Merci pour vos réponses,

Matt...



Cordialement,
Pascal
Avatar
bertrand
Pascal a écrit :
Matt a écrit :
Bonjour,



Bonjour,

// Constructeur Individu
var MyIndividu = function()
{
// Recuperation des donnees
if(arguments.length == 1)
this.nom = arguments[0] ;
}



JS est très souple au niveau du passage d'arguments, pas besoin de
s'assurer s'ils ont bien été passés.
Sauf, bien sûr, s'ils sont impliqués dans la construction de l'objet
mais, dans le cas présent, j'utiliserais plutôt un "setter" pour le nom,
donc une méthode genre "setNom(nom)", pour être cohérent avec la méthode
"setIndividu()" définie plus bas.

// Nom
MyIndividu.prototype.nom = "";



C'est théoriquement correct, mais là je ne vois pas l'intérêt du
prototypage.

Je n'en connais que deux usages intéressants :
1. Eviter d'encombrer la mémoire dès la création d'un nouvel objet. Pour
une propriété, ça vaut le coup si elle est de type composée, et a
fortiori de type objet, mais pas scalaire comme ici.
2. Modulariser le code, ce qui va de soi pour une méthode, mais pas trop
pour une propriété.

// Affichage de l'individu
MyIndividu.prototype.affiche = function()
{
alert(""" + this.nom + """);
}



On va dire que la méthode "alert()" est là seulement pour mettre quelque
chose.
Si c'est pour le débogage, je conseillerai plutôt "console.log()".

// Constructeur Agenda
var MyAgenda = function()
{
this.listeIndividu = new Array();
}



Pas cohérent avec l'initialisation du nom qui est une chaîne littérale.
Donc, soit le nom est initialisé avec "new String", soit la liste est
initialisée avec "[]".

// Liste des individus
MyAgenda.prototype.listeIndividu = null;



Pourquoi prototyper, puisque la liste est définie dans le constructeur ?
Cela dit, comme c'est une liste d'objets (qui peuvent donc grossir) je
préfère cette solution, mais alors il ne faut pas la définir avant !

// On enregistre un nouvel individu
MyAgenda.prototype.setIndividu = function()
{
var newIndividu = new MyIndividu(arguments[0]);
this.listeIndividu.push(newIndividu);
}



Pareil que ma première remarque, autant passer un argument nommé à la
méthode "setIndividu(nom)".

// On affiche tout les individus
MyAgenda.prototype.getAllIndividu = function()
{
for(var i = 0; i < this.listeIndividu.length; i++)
this.listeIndividu[i].affiche();
}



Petite astuce au cas où la liste serait importante : la condition de
répétition de la boucle est évaluée avant chaque passage, donc mieux
vaut définir une variable égale au nombre d'éléments à traiter juste
avant la boucle, ce sera plus rapide.
Par exemple :
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++) { ... }

Une question d'appellation , qu'est ce que MyAgenda ? peut on parler
d'une classe et quand on l'instancie peut on parler d'un objet.



Avec les versions 1.x, pas vraiment. La version 2 introduit la notion de
classe et d'instanciation, mais elle n'est implémentée que dans les
moteurs ActionScript.
Donc, pour les moteurs JS des clients Web, ce ne sont que des objets
primitifs que l'on copie avec le mot clé "new", d'où la notion générale
de prototypage associée à ce langage (cela fait partie de son paradigme).

Merci pour vos réponses,

Matt...



Cordialement,
Pascal




Bonsoir,

D'abord merci pour votre réponse.
J'ai refait mes deux objets en tenant compte de vos remarques et je me
permet de re-poster afin de voir si j'ai bien compris le principe et les
soumettre à vos critiques constructives.

/**Individu**/
var MyIndividu = function()
{
}

MyIndividu.prototype.setNom = function(nom)
{
this.nom = nom;
}

MyIndividu.prototype.getNom = function()
{
return this.nom;
}
/**********/

/**Agenda**/
var MyAgenda = function()
{
}

MyAgenda.prototype.listeIndividu = new Array();

MyAgenda.prototype.setIndividu = function(nom)
{
var newIndividu = new MyIndividu();
newIndividu.setNom(nom);

this.listeIndividu.push(newIndividu);
}

MyAgenda.prototype.getAllIndividu = function()
{
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++)
alert(this.listeIndividu[i].getNom());
}
/*********/


Voila, merci pour vos remarques.

Matt...
Avatar
Pascal
bertrand a écrit :
/**Individu**/
var MyIndividu = function()
{
}

MyIndividu.prototype.setNom = function(nom)
{
this.nom = nom;
}

MyIndividu.prototype.getNom = function()
{
return this.nom;
}
/**********/

/**Agenda**/
var MyAgenda = function()
{
}

MyAgenda.prototype.listeIndividu = new Array();

MyAgenda.prototype.setIndividu = function(nom)
{
var newIndividu = new MyIndividu();
newIndividu.setNom(nom);

this.listeIndividu.push(newIndividu);
}

MyAgenda.prototype.getAllIndividu = function()
{
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++)
alert(this.listeIndividu[i].getNom());
}
/*********/


Voila, merci pour vos remarques.



Rien à dire, pour ma part.

Cordialement,
Pascal
Avatar
Mickaël Wolff
Pascal a écrit :

JS est très souple au niveau du passage d'arguments, pas besoin de
s'assurer s'ils ont bien été passés.



Je ne comprends pas cette remarque. this.nom = arguments[0] est
undefined et non pas une chaine, Il assure la cohérence de ses attributs.

Sauf, bien sûr, s'ils sont impliqués dans la construction de l'objet
mais, dans le cas présent, j'utiliserais plutôt un "setter" pour le nom,
donc une méthode genre "setNom(nom)", pour être cohérent avec la méthode
"setIndividu()" définie plus bas.



Je ne suis pas fan de ce type de setter. Je préfère utiliser
l'attribut directement, en tant qu'interface de l'objet.


C'est théoriquement correct, mais là je ne vois pas l'intérêt du
prototypage.

Je n'en connais que deux usages intéressants :
1. Eviter d'encombrer la mémoire dès la création d'un nouvel objet. Pour
une propriété, ça vaut le coup si elle est de type composée, et a
fortiori de type objet, mais pas scalaire comme ici.



Dans l'absolu, les scalaires n'existent pas en javascript, il n'y a
que des objets ;)

2. Modulariser le code, ce qui va de soi pour une méthode, mais pas trop
pour une propriété.



Tu peux expliquer ?

var newIndividu = new MyIndividu(arguments[0]);
this.listeIndividu.push(newIndividu);
}



Pareil que ma première remarque, autant passer un argument nommé à la
méthode "setIndividu(nom)".



Ici c'est vrai que ça n'a pas de sens. Bien que dans le constructeur
par défaut du prototype ça en avait un. Il n'y a pas moyen de déclarer
des arguments par défaut (me semble-t-il.


// On affiche tout les individus
MyAgenda.prototype.getAllIndividu = function()
{
for(var i = 0; i < this.listeIndividu.length; i++)
this.listeIndividu[i].affiche();
}



Petite astuce au cas où la liste serait importante : la condition de
répétition de la boucle est évaluée avant chaque passage, donc mieux
vaut définir une variable égale au nombre d'éléments à traiter juste
avant la boucle, ce sera plus rapide.
Par exemple :
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++) { ... }



En quoi ce serait plus rapide ? Un Array connais toujours sa taille
en temps constant. J'aurais plutot parlé de Array.forEach ou Array.map.

Avec les versions 1.x, pas vraiment. La version 2 introduit la notion de
classe et d'instanciation, mais elle n'est implémentée que dans les
moteurs ActionScript.



Il n'y a pas de notion de classe dans Ecmascript, mais uniquement
d'objets. 'fin, pour l'instant. je n'ai pas encore lu la dernière norme.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Pascal
Bonjour,

C'est un peu la critique pour la critique, je ne suis pas sûr que cela
apporte grand chose à notre ami qui se demandait si son code était bi en
construit.
Mais bon, allez, je me prête volontiers au jeu.

Mickaël Wolff a écrit :
Pascal a écrit :

JS est très souple au niveau du passage d'arguments, pas besoin de
s'assurer s'ils ont bien été passés.



Je ne comprends pas cette remarque. this.nom = arguments[0] est
undefined et non pas une chaine, Il assure la cohérence de ses attrib uts.



Simplement pour préciser que JS ne génère pas d'erreur si, alors qu 'une
fonction prévoit un ou plusieurs arguments, on ne lui en passe que
quelques uns, voire aucun.
De ce fait, le tableau "arguments[]" n'est vraiment utile que lorsqu'on
ne peut nommer les arguments et que leur nombre est variable. Mais, dans
ce cas, je trouve plus élégant de passer un seul argument nommé, so us
forme de tableau.

Sauf, bien sûr, s'ils sont impliqués dans la construction de l'obj et
mais, dans le cas présent, j'utiliserais plutôt un "setter" pour l e
nom, donc une méthode genre "setNom(nom)", pour être cohérent av ec la
méthode "setIndividu()" définie plus bas.



Je ne suis pas fan de ce type de setter. Je préfère utiliser
l'attribut directement, en tant qu'interface de l'objet.



Moi non plus, je n'abuse pas des "setters". C'était juste pour mainteni r
la cohérence du code qui était présenté, avec la méthode déjà existante
"setIndividu()".

C'est théoriquement correct, mais là je ne vois pas l'intérêt du
prototypage.

Je n'en connais que deux usages intéressants :
1. Eviter d'encombrer la mémoire dès la création d'un nouvel obj et.
Pour une propriété, ça vaut le coup si elle est de type composé e, et a
fortiori de type objet, mais pas scalaire comme ici.



Dans l'absolu, les scalaires n'existent pas en javascript, il n'y a
que des objets ;)



C'est une légende. La preuve :

<script>
var texte_1 = "essai"; // littéral => scalaire
alert(typeof texte_1); // 'string'
texte_1.toUpperCase(); // passage temporaire en objet + méthode
alert(typeof texte_1); // toujours 'string'
var texte_2 = new String("essai"); // constructeur => objet
alert(typeof texte_2); // 'object'
texte_2.toUpperCase(); // méthode directe sur objet
alert(typeof texte_2); // toujours 'object'
var texte_3 = String(texte_2); // fonction de transtypage
alert(typeof texte_3); // à nouveau 'string'
</script>


2. Modulariser le code, ce qui va de soi pour une méthode, mais pas
trop pour une propriété.



Tu peux expliquer ?



Simple. Il y a infiniment moins de raison d'avoir à modifier une
propriété que de toucher au code d'une méthode.
D'ailleurs que pourrait-on changer, à part son nom ou sa valeur par dé faut ?

// On affiche tout les individus
MyAgenda.prototype.getAllIndividu = function()
{
for(var i = 0; i < this.listeIndividu.length; i++)
this.listeIndividu[i].affiche();
}



Petite astuce au cas où la liste serait importante : la condition de
répétition de la boucle est évaluée avant chaque passage, donc mieux
vaut définir une variable égale au nombre d'éléments à trait er juste
avant la boucle, ce sera plus rapide.
Par exemple :
var nbIndividus = this.listeIndividu.length;
for(var i = 0; i < nbIndividus; i++) { ... }



En quoi ce serait plus rapide ? Un Array connais toujours sa taille e n
temps constant. J'aurais plutot parlé de Array.forEach ou Array.map.



Comprends pas, l'histoire de "temps constant". Mais il me semble que JS
doive recalculer la taille à chaque fois qu'on lui demande, non ?
Quant à "forEach" et "map", je trouve un peu risquer de les utiliser su r
le Web, ils sont trop récents.

Avec les versions 1.x, pas vraiment. La version 2 introduit la notion
de classe et d'instanciation, mais elle n'est implémentée que dans les
moteurs ActionScript.



Il n'y a pas de notion de classe dans Ecmascript, mais uniquement
d'objets. 'fin, pour l'instant. je n'ai pas encore lu la dernière nor me.



C'est vrai pour ECMAScript, quoique l'édition 4 ait discuté ce point.
Mais une proposition de Netscape, reprise par ActionScript, a remis en
question les notions de classe et de typage fort dans l'hypothétique
version 2.0 de JavaScript.
Voir [http://www.mozilla.org/js/language/evolvingJS.pdf]
C'est bien sûr une tentative de coller à Java, et ça ne plait vraim ent
pas à Brendan Eich !
Voir [https://developer.mozilla.org/presentations/xtech2006/javascript/]

Cordialement,
Pascal
Avatar
Olivier Miakinen
Le 20/01/2010 12:18, Pascal répondait à Mickaël Wolff :

Dans l'absolu, les scalaires n'existent pas en javascript, il n'y a
que des objets ;)



C'est une légende.



La norme ECMAScript, 3e édition, définit neuf types différents. Parmi
ceux-ci, trois ne sont utilisés qu'en interne (ou peut-être même pas,
quoique ils soient utilisés pour décrire les algorithmes) et ne peuvent
pas être utilisés dans des propriétés d'objets.

Les six « vrais » types sont :
- Undefined (qui n'a qu'une seule valeur possible, undefined)
- Null (qui n'a qu'une seule valeur possible, null)
- Boolean (qui n'a que deux valeurs possibles, true et false)
- String
- Number
- Object
Avatar
Mickaël Wolff
Pascal a écrit :
Bonjour,

C'est un peu la critique pour la critique, je ne suis pas sûr que cela
apporte grand chose à notre ami qui se demandait si son code était bien
construit.
Mais bon, allez, je me prête volontiers au jeu.



Je voulais faire une réponse constructive, mais tu m'as coupé l'herbe
sous les pieds en m'énervant avec des affirmations que je ne cautionne pas.

Simplement pour préciser que JS ne génère pas d'erreur si, alors qu'une
fonction prévoit un ou plusieurs arguments, on ne lui en passe que
quelques uns, voire aucun.
De ce fait, le tableau "arguments[]" n'est vraiment utile que lorsqu'on
ne peut nommer les arguments et que leur nombre est variable. Mais, dans
ce cas, je trouve plus élégant de passer un seul argument nommé, sous
forme de tableau.



Tu parle d'une élégance ! J'ai déjà du mal à trouver ça élégant en
PHP, alors en Javascript, où on a la chance d'avoir un tableau nommé
recensant les arguments... L'objet arguments existe déjà, pour s'embeter
avec un nouvel inutile ? A moins que tu ne parles d'utiliser
Object.call ou Object.apply, mais dans ce cas c'est bien l'objet
arguments que tu utilises.


Dans l'absolu, les scalaires n'existent pas en javascript, il n'y a
que des objets ;)



C'est une légende. La preuve :



...

<script>
var texte_1 = "essai"; // littéral => scalaire



Ceci est effectivement une représentation litérale, qui entraine
l'instanciation d'un objet String qui ne dit malheureusement pas son nom.

alert(typeof texte_1); // 'string'
texte_1.toUpperCase(); // passage temporaire en objet + méthode



Il n'y a pas de passage par un objet temporaire pour appeler la
méthode. texte_1 *est* un objet. Si 'toto' n'est pas un objet, comment
se fait-il qu'il possède constructor ?

En quoi ce serait plus rapide ? Un Array connais toujours sa taille
en temps constant. J'aurais plutot parlé de Array.forEach ou Array.map.



Comprends pas, l'histoire de "temps constant". Mais il me semble que JS
doive recalculer la taille à chaque fois qu'on lui demande, non ?



Non :) La taille est mise à jour à chaque insert ou delete.

Quant à "forEach" et "map", je trouve un peu risquer de les utiliser sur
le Web, ils sont trop récents.



Utiliser Javascript est en soit dangereux ;)


C'est vrai pour ECMAScript, quoique l'édition 4 ait discuté ce point.
Mais une proposition de Netscape, reprise par ActionScript, a remis en
question les notions de classe et de typage fort dans l'hypothétique
version 2.0 de JavaScript.
Voir [http://www.mozilla.org/js/language/evolvingJS.pdf]
C'est bien sûr une tentative de coller à Java, et ça ne plait vraiment
pas à Brendan Eich !
Voir [https://developer.mozilla.org/presentations/xtech2006/javascript/]



Et je penche dans son sens. Ecmascript dispose de paradigmes dans une
combinaison unique, qui lui permettent d'etre un langage souple et
adapté à la gestion d'interfaces utilisateur. Ce serait dommage de
perdre ces avantages, rien que pour permettre aux armées de développeurs
lobotomisés au Java puissent prendre d'assaut cet étrange contrée qu'est
le DOM.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
WebShaker
La premiere methode, celle qui consiste a associer les methode a l'objet via
this offre un avantage certain.
Celui de l'heritage...

Avec le prototypage.
pas d'héritage possible (en tout cas moi j'ai pas trouvé !!!)

Etienne

"bertrand" a écrit dans le message de news:
4b45bbe1$0$3681$
Bonjour,

Quelle est la meilleur façon de créer un objet :

function MyObjet()
{
this.myPropriete = 0;

this.MyMethode = function(arg)
{
alert(arg);
}
}

ou alors

function MyObjet()
{
this.myPropriete = 0;
}

MyObjet.prototype.MyMethode = function(arg)
{
this.myPropriete += arg;
alert(myPropriete);
}

Dans le deuxième cas, on ne peut ni avoir de méthode, ni de propriété
privés, tout est public.

Merci pour vos réponses,

Matt...


Avatar
Mickaël Wolff
WebShaker a écrit :
La premiere methode, celle qui consiste a associer les methode a l'objet via
this offre un avantage certain.
Celui de l'heritage...

Avec le prototypage.
pas d'héritage possible (en tout cas moi j'ai pas trouvé !!!)



Mal cherché ?

var base = function() { }
base.prototype.run = function() { print('Run in base') }

var derived = function() { }
derived.prototype = new base ;

var o = new derived ;
o.run() ;

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
1 2 3