IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

L'opérateur new, bonne ou mauvaise pratique ? [Tutoriel]


Sujet :

JavaScript

  1. #41
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Citation Envoyé par kaari kosaku Voir le message
    j'ai développé une peur profonde de ".prototype".
    Citation Envoyé par SylvainPV Voir le message
    comment en est-on arrivé à avoir peur des prototypes alors qu'ils sont un des piliers fondateurs du langage ?
    Je reformule : Où ça fait peur ?

    Précedemment, je soulignais que la création se passait de façon similaire: héritage d'objet à objet, l'initialisation est différente.

    D'où la question.

    Les patterns que tu as identifé dans ton code,
    Citation Envoyé par SylvainPV Voir le message
    Deuxio, certains patterns revenaient souvent et j'ai pris rapidement quelques réflexes :
    - remplacer les fonctions constructeurs par une fonction create:
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var Model = Object.create({
      create: function(arg){
        var model = Object.create(Model );
          model.property = arg;
          return model;
        },
        method: function(){ ... }
    });
    peuvent trés bien se réécrire avec un 'constructor' protégé comme fonction au lieu de 'create'. Pratiquement le même pattern, seul le contenu de la fonction 'create' et son nom change. Rajout de Model.constructor.prototype = Model; qui ne fait pas partie du pattern d'origine, c'est vrai (il suffirait de l'intégrer à une fonction générant le constructeur et ainsi gérer la même cloture mais ok).

    Même pattern => mêmes avantages. En conservant la possibilité de gérer deux contextes d'appels, et la richesse sémantique.

    J'ai tordu ce modèle (Ctor+proto) dans tous les sens pratiquement depuis son apparition, ma conclusion est que : quelque soit le "pattern" utilisé tu écris toujours la même chose. C'est ce que j'essayais de présenter.

    Bien. Je vais redevenir simple lecteur de cet excellent site.
    Merci et bon we à tous

  2. #42
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    J'ai proposé ce pattern comme une alternative aux constructeurs, et tu me proposes comme alternative d'y revenir... Est-ce qu'on ne tournerait pas en rond ?

    On peut instancier un objet de multiples façons et décliner la fonction create en X autres versions, donc gérer autant de contextes d'appels différents que nécessaire. Quant à la richesse sémantique, il s'agit purement de conventions et je ne vois pas en quoi new serait sémantiquement plus riche que Object.create.

    En revanche, toute l'argumentation faite jusqu'ici contre cette propriété constructor tient toujours :
    - on n'a pas besoin de fonctions constructeurs pour faire de l'héritage d'objet, or new nous oblige à les utiliser et à les garder en référence
    - en passant par new, on a pas le choix du nom "constructor". Or la propriété constructor peut être surchargée volontairement ou non. Si j'ai un modèle voiture avec une propriété constructor (megane.constructor = "Renault"), la référence est compromise
    - pour cette même raison, on ne peut pas s'en servir de manière sûre pour récupérer le modèle d'une instance (contrairement à Object.getPrototypeOf)
    One Web to rule them all

  3. #43
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Petit up pour mentionner deux excellents articles d'Eric Eliott sur le sujet :
    https://medium.com/javascript-scene/...d-2d42bb3f4caf
    https://medium.com/javascript-scene/...t-d5d9bab29b0a

    Si je trouve le temps, je tâcherais de les traduire en français. Son argumentaire est bien plus complet et réfléchi que le mien pour exposer tous les défauts des opérateurs "new", "instanceof" et "class".
    One Web to rule them all

  4. #44
    Invité
    Invité(e)
    Par défaut
    Bonjour, lorsque j'ai débuté avec les objets Javascripts, je les créais avec NEW.
    Je faisais un constructeur associé à cet objet et des méthodes associées ... puis batatras, ça marchait bien...

    Puis après, je me suis rendu compte qu'on pouvait modifier directement les objets JSON en LIVE avec Angular...
    Du coup, je n'utilise plus de new, je modifie directement mes objets avec Angular dans une boucle for.

    ça fait du style :

    $scope.monObjet = {"nom":"Durand";"prenom":"Patrick"}

    Puis après , je fais une boucle for pour modifier mon objet .

    Ou même pire, Le nom dans l'objet $scope.monObjet peut être modifié directement en tant que champs INPUT Html, dans une page HTML, par le live Binding d'Angular... Alors pourquoi encore s'embêter avec des opérateurs New ?


    Je ne sais pas trop ce que vous en pensez ? Du coup, je ne me sers plus de New en ce moment.

  5. #45
    Membre expérimenté
    Homme Profil pro
    chomeur
    Inscrit en
    Avril 2015
    Messages
    709
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : chomeur
    Secteur : Distribution

    Informations forums :
    Inscription : Avril 2015
    Messages : 709
    Points : 1 582
    Points
    1 582
    Par défaut
    j'ai fait quelques testes afin de comparer new et objet.create pour ce faire je suis parti sur la base d'un script utilisant new que j'ai transformé en objet literal sans modification des fonction afin d'etre instancié avec objet.create.

    pour le script utilisant new j'ai la fonction constructeur comportant des attributs et les fonctions sont declaré en utilisant prototype il y a aussi un attribut qui utilise prototype et qui est assigné durant l'execution du script

    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
    155
    156
    157
    158
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
     
    <style type="text/css">
     
    #trtt span{
    	background:red;
    	cursor:pointer;
    }
     
    .dg{
    	position:absolute;
    }
     
    .dg div{
    	background-color:#bbbbbb;
    	width:110px;
    	border:1px;
    	border-style:solid;
    	cursor:pointer;
    	color:white;
    }
     
    </style>
     
    <script>			
     
    function syno_c(conteneur,lui){
     
    this.conteneur=document.getElementById(conteneur);
     
    this.out_b=this.out.bind(this);
     
    this.nom=lui;
    }
     
    syno_c.prototype.synonymes={
     
    		"tir": ["frappe","shoot","coup de pied"],
    		"passe": ["transmission","échange","remise","une-deux"],
    		"arrêt": ["passe","parade","plongeon","sauvetage","claquette"],
    		"dribble": ["technique","crochets","enfumage","gri-gri"],
    		"victoire": ["succès","réussite","triomphe","gain"],
    		"chance": ["réussite","aubaine","bonheur","hasard"],
    		"occasion": ["action","enchaînement"],
    		"arbitre": ["homme en noir"],
    		"gardien": ["portier","dernier rempart"]
    	}
     
    syno_c.prototype.dg='';
     
     
     
    syno_c.prototype.dina=function (){
     
    		var txt=this.conteneur.textContent;
    		this.conteneur.innerHTML='';
     
    		var tbphrase=txt.split(' ');
    		var pvpv=[];
     
    		for(var i=0;i<tbphrase.length;i++){
     
    			if(tbphrase[i].indexOf('.', 0) != -1 || tbphrase[i].indexOf(',', 0)!= -1 || tbphrase[i].indexOf('?', 0)!= -1  || tbphrase[i].indexOf('!', 0) != -1 || tbphrase[i].indexOf(';', 0)!= -1){
     
    				var rev=tbphrase[i].substr(tbphrase[i].length-1, 1);	
    			}
    			else{
    				var rev=null;
    			}
    			pvpv.push(rev);
    			tbphrase[i]=tbphrase[i].replace(rev,'');
    		}
     
    		for(var i=0;i<tbphrase.length;i++){	
     
    			var mot=tbphrase[i];
     
    			for(var j=i+1;j<tbphrase.length;j++){
     
    				if(tbphrase[j]==mot && this.synonymes[mot]){
     
    					tbphrase[j]='<span onclick="'+this.nom+'.choix(this,event,\''+mot+'\')">'+tbphrase[j]+'</span>';
    				}
    			}
    		}
     
    		for(var i=0;i<tbphrase.length;i++){
     
    			if(pvpv[i]!=null){
    				tbphrase[i]+=pvpv[i];
    			}
    		}
    		var phrase=	tbphrase.join(" ");
    		this.conteneur.innerHTML=phrase;
    	}
     
     
    syno_c.prototype.choix=function(lui,e,mot){
     
    		this.dg=='' ? this.dg=document.createElement('div') : this.dg.innerHTML='';
     
    		this.dg.className='dg';
    		this.dg.style.display='block';
    		this.dg.style.left=e.pageX+10+'px';
    		this.dg.style.top=e.pageY+20+'px';
     
    		for(var i=0;i<=this.synonymes[mot].length;i++){
     
    			var crea=document.createElement('div');
    			crea.textContent=this.synonymes[mot][i];
    			var mt=this.synonymes[mot][i]
     
    			this.add(crea,mt,lui)
     
    			this.dg.appendChild(crea);
    			document.body.appendChild(this.dg);
    		}
    		document.addEventListener('mouseup',this.out_b,false);
    	}
     
    syno_c.prototype.add=function(crea,mt,lui){
     
    		var that=this;
    		crea.onclick=function(){lui.innerHTML=mt;that.dg.style.display='none';lui.style.backgroundColor="transparent";that.dina()}
    	}
     
     
    syno_c.prototype.out=function(crea,mt,lui){
    		this.dg.style.display='none';
    		document.removeEventListener('mouseup',this.out_b,false);
    	}
     
     
     
    function syno_instance(){
     
    	is=new syno_c('trtt','is');
     
    	document.getElementById('bb').onclick=function(){is.dina()}
     
    }
     
    window.addEventListener("load",syno_instance, false);
     
    </script>
    </head>
    <body>
    <br>
     
    <div id="trtt" class="editable" contenteditable="true" style='overflow:auto;width:400px;height:140px'>
        le joueur de football a réalisé un très beau tir. Ce tir, est venu se loger en pleine lucarne, le gardien a rien pu faire. c'est un tir exceptionnel que le gardien ne pouvait arreter.
    </div>
    <button id='bb'>azerty</button>
    </body>
    <html>
    voila ce que me donne la console.

    Nom : 1a.jpg
Affichages : 263
Taille : 6,7 Ko

    Nom : 1b.jpg
Affichages : 260
Taille : 24,0 Ko


    au tour de objet.create tout est declaré dans un objet literal et la je constate que quand je cree l'instance tout est prototype l'objet est vide enfin presque car au moment de l'instentiation je cree des attribut involontairement pensant que je suis en train d'assigné des valeurs aux attributs deja declarés.

    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
    155
    156
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
     
    <style type="text/css">
     
    #trtt span{
    	background:red;
    	cursor:pointer;
    }
     
    .dg{
    	position:absolute;
    }
     
    .dg div{
    	background-color:#bbbbbb;
    	width:110px;
    	border:1px;
    	border-style:solid;
    	cursor:pointer;
    	color:white;
    }
     
    </style>
     
    <script>			
     
    var syno_c={
     
     
    	conteneur:'',
    	nom:'',
    	out_b:'',
     
    	synonymes :  {
     
    		"tir": ["frappe","shoot","coup de pied"],
    		"passe": ["transmission","échange","remise","une-deux"],
    		"arrêt": ["passe","parade","plongeon","sauvetage","claquette"],
    		"dribble": ["technique","crochets","enfumage","gri-gri"],
    		"victoire": ["succès","réussite","triomphe","gain"],
    		"chance": ["réussite","aubaine","bonheur","hasard"],
    		"occasion": ["action","enchaînement"],
    		"arbitre": ["homme en noir"],
    		"gardien": ["portier","dernier rempart"]
    	},
     
    	dg :'',
     
    	dina : function (){
     
    		var txt=this.conteneur.textContent;
    		this.conteneur.innerHTML='';
     
    		var tbphrase=txt.split(' ');
    		var pvpv=[];
     
    		for(var i=0;i<tbphrase.length;i++){
     
    			if(tbphrase[i].indexOf('.', 0) != -1 || tbphrase[i].indexOf(',', 0)!= -1 || tbphrase[i].indexOf('?', 0)!= -1  || tbphrase[i].indexOf('!', 0) != -1 || tbphrase[i].indexOf(';', 0)!= -1){
     
    				var rev=tbphrase[i].substr(tbphrase[i].length-1, 1);	
    			}
    			else{
    				var rev=null;
    			}
    			pvpv.push(rev);
    			tbphrase[i]=tbphrase[i].replace(rev,'');
    		}
     
    		for(var i=0;i<tbphrase.length;i++){	
     
    			var mot=tbphrase[i];
     
    			for(var j=i+1;j<tbphrase.length;j++){
     
    				if(tbphrase[j]==mot && this.synonymes[mot]){
     
    					tbphrase[j]='<span onclick="'+this.nom+'.choix(this,event,\''+mot+'\')">'+tbphrase[j]+'</span>';
    				}
    			}
    		}
     
    		for(var i=0;i<tbphrase.length;i++){
     
    			if(pvpv[i]!=null){
    				tbphrase[i]+=pvpv[i];
    			}
    		}
    		var phrase=	tbphrase.join(" ");
    		this.conteneur.innerHTML=phrase;
    	},
     
     
    	choix : function(lui,e,mot){
     
    		this.dg=='' ? this.dg=document.createElement('div') : this.dg.innerHTML='';
     
    		this.dg.className='dg';
    		this.dg.style.display='block';
    		this.dg.style.left=e.pageX+10+'px';
    		this.dg.style.top=e.pageY+20+'px';
     
    		for(var i=0;i<=this.synonymes[mot].length;i++){
     
    			var crea=document.createElement('div');
    			crea.textContent=this.synonymes[mot][i];
    			var mt=this.synonymes[mot][i]
     
    			this.add(crea,mt,lui)
     
    			this.dg.appendChild(crea);
    			document.body.appendChild(this.dg);
    		}
    		document.addEventListener('mouseup',this.out_b,false);
    	},
     
    	add : function(crea,mt,lui){
     
    		var that=this;
    		crea.onclick=function(){lui.innerHTML=mt;that.dg.style.display='none';lui.style.backgroundColor="transparent";that.dina()}
    	},
     
     
    	out : function(crea,mt,lui){
    		this.dg.style.display='none';
    		document.removeEventListener('mouseup',this.out_b,false);
    	}
     
    }
     
     
    function syno_instance(){
     
    	is=Object.create(syno_c);
    	is.conteneur=document.getElementById('trtt');
    	is.out_b=is.out.bind(is);
    	is.nom='is';
    	document.getElementById('bb').onclick=function(){is.dina()}
    }
     
    window.addEventListener("load",syno_instance, false);
     
    </script>
    </head>
    <body>
    <br>
     
    <div id="trtt" class="editable" contenteditable="true" style='overflow:auto;width:400px;height:140px'>
        le joueur de football a réalisé un très beau tir. Ce tir, est venu se loger en pleine lucarne, le gardien a rien pu faire. c'est un tir exceptionnel que le gardien ne pouvait arreter.
    </div>
    <button id='bb'>azerty</button>
    </body>
    <html>
    ce qui donne dans la console.

    Nom : 2a.jpg
Affichages : 259
Taille : 6,2 Ko
    Nom : 2b.jpg
Affichages : 256
Taille : 20,6 Ko

    et la dans mon cas je me dit a quoi sa sert d'utiliser objet.create si je doit passer par une etape de creation des attributs autant utiliser new et la fonction constructeur qui me permet de creer ces attributs.


    aller un petit dernier pour la route cette fois en utilisant class de ecmascript 6 avec firefox 40 l'instance se faisant avec new

    pour commencer on declare la class avec le mot class{} puis a l'interieur de cette class on declare les attributs avec le mot constructeur{} et enfin on declare les fonction sans utiliser le mot fonction, et la petit probleme car apparement hormis dans le constructeur on ne peut apparement pas declarer d'attribut et d'objets. J'ai quand meme reussi a les declaré a l'interieur du constructeur en utilisant __proto__. Quand a l'instanciation elle est similaire a celle utilisant new.

    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
    155
    156
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
     
    <style type="text/css">
     
    #trtt span{
    	background:red;
    	cursor:pointer;
    }
     
    .dg{
    	position:absolute;
    }
     
    .dg div{
    	background-color:#bbbbbb;
    	width:110px;
    	border:1px;
    	border-style:solid;
    	cursor:pointer;
    	color:white;
    }
     
    </style>
     
    <script>			
     
    class syno_c {
     
    	constructor(conteneur,lui) {
     
    		this.conteneur=document.getElementById(conteneur);
     
    		this.out_b=this.out.bind(this);
     
    		this.nom=lui;
     
    		this.__proto__.dg='';
     
    		this.__proto__.synonymes={
     
    		"tir": ["frappe","shoot","coup de pied"],
    		"passe": ["transmission","échange","remise","une-deux"],
    		"arrêt": ["passe","parade","plongeon","sauvetage","claquette"],
    		"dribble": ["technique","crochets","enfumage","gri-gri"],
    		"victoire": ["succès","réussite","triomphe","gain"],
    		"chance": ["réussite","aubaine","bonheur","hasard"],
    		"occasion": ["action","enchaînement"],
    		"arbitre": ["homme en noir"],
    		"gardien": ["portier","dernier rempart"]
    		}
    	}
     
     
    	dina(){
     
    		var txt=this.conteneur.textContent;
    		this.conteneur.innerHTML='';
     
    		var tbphrase=txt.split(' ');
    		var pvpv=[];
     
    		for(var i=0;i<tbphrase.length;i++){
     
    			if(tbphrase[i].indexOf('.', 0) != -1 || tbphrase[i].indexOf(',', 0)!= -1 || tbphrase[i].indexOf('?', 0)!= -1  || tbphrase[i].indexOf('!', 0) != -1 || tbphrase[i].indexOf(';', 0)!= -1){
     
    				var rev=tbphrase[i].substr(tbphrase[i].length-1, 1);	
    			}
    			else{
    				var rev=null;
    			}
    			pvpv.push(rev);
    			tbphrase[i]=tbphrase[i].replace(rev,'');
    		}
     
    		for(var i=0;i<tbphrase.length;i++){	
     
    			var mot=tbphrase[i];
     
    			for(var j=i+1;j<tbphrase.length;j++){
     
    				if(tbphrase[j]==mot && this.synonymes[mot]){
     
    					tbphrase[j]='<span onclick="'+this.nom+'.choix(this,event,\''+mot+'\')">'+tbphrase[j]+'</span>';
    				}
    			}
    		}
    	for(var i=0;i<tbphrase.length;i++){
     
    			if(pvpv[i]!=null){
    				tbphrase[i]+=pvpv[i];
    			}
    		}
    		var phrase=	tbphrase.join(" ");
    		this.conteneur.innerHTML=phrase;
    	}
     
    	choix(lui,e,mot){
     
    		this.dg=='' ? this.dg=document.createElement('div') : this.dg.innerHTML='';
     
    		this.dg.className='dg';
    		this.dg.style.display='block';
    		this.dg.style.left=e.pageX+10+'px';
    		this.dg.style.top=e.pageY+20+'px';
     
    		for(var i=0;i<=this.synonymes[mot].length;i++){
     
    			var crea=document.createElement('div');
    			crea.textContent=this.synonymes[mot][i];
    			var mt=this.synonymes[mot][i]
     
    			this.add(crea,mt,lui)
     
    			this.dg.appendChild(crea);
    			document.body.appendChild(this.dg);
    		}
    		document.addEventListener('mouseup',this.out_b,false);
    	}
     
    	add(crea,mt,lui){
     
    		var that=this;
    		crea.onclick=function(){lui.innerHTML=mt;that.dg.style.display='none';lui.style.backgroundColor="transparent";that.dina()}
    	}
     
    	out(crea,mt,lui){
    		this.dg.style.display='none';
    		document.removeEventListener('mouseup',this.out_b,false);
    	}
    }
     
     
    function syno_instance(){
     
    	is=new syno_c('trtt','is');
     
    	document.getElementById('bb').onclick=function(){is.dina()}
     
    }
     
    window.addEventListener("load",syno_instance, false);
     
    </script>
    </head>
    <body>
    <br>
     
    <div id="trtt" class="editable" contenteditable="true" style='overflow:auto;width:400px;height:140px'>
        le joueur de football a réalisé un très beau tir. Ce tir, est venu se loger en pleine lucarne, le gardien a rien pu faire. c'est un tir exceptionnel que le gardien ne pouvait arreter.
    </div>
    <button id='bb'>azerty</button>
    </body>
    <html>
    le resultat dans la console.

    Nom : 3a.jpg
Affichages : 258
Taille : 6,2 Ko



    finalement la reflection que je me fait c'est que tous ca sa devient compliquer et que de toute facon on parle toujour d'objet avec prototype mais bon sa concerne ma facon de pratiqué la poo
    Plus vite encore plus vite toujours plus vite.

  6. #46
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Salut,

    En JS je trouve que c'est difficile de s'y retrouver, il y a beaucoup de façons de faire les choses et tu as des auteurs qui défendent telle ou telle manière de faire et pour un débutant c'est trop déroutant...

    Citation Envoyé par SylvainPV Voir le message

    Et si je souhaite ajouter le constructeur de la voiture dans mon modèle Car ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Car(constructor, model){
       this.model = model;
       this.constructor = constructor;
       this.speed = 0;
    }
     
    var golf = new Car("Volkswagen","Golf");
     
    golf.constructor === Car; // false !
    Au lieu de golf.constructor === Car; // false ! on pourrait faire ça :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    console.log(Object.getPrototypeOf(golf).constructor === Car); /// true
    // ou
    console.log(golf.__proto__.constructor === Car); //true

    non ?
    ------------------------------------------

    Citation Envoyé par SylvainPV Voir le message
    Petit up pour mentionner deux excellents articles d'Eric Eliott sur le sujet :
    https://medium.com/javascript-scene/...d-2d42bb3f4caf
    https://medium.com/javascript-scene/...t-d5d9bab29b0a

    Si je trouve le temps, je tâcherais de les traduire en français. Son argumentaire est bien plus complet et réfléchi que le mien pour exposer tous les défauts des opérateurs "new", "instanceof" et "class".
    Merci. Alors j'ai vu que tu as traduit un des articles ici : https://sylvainpv.developpez.com/tra...usses-heritage (je ne l'ai pas encore lu) alors je me demandais si l'autre aussi a été traduit ?

  7. #47
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Amusant ce up d'un post d'il y a 3 ans, j'y étais justement revenu hier pour développer mon idée avec une nouvelle approche pour le problème du debugging qui m'avait bloqué à l'époque.

    La ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    golf.constructor === Car; // false !
    a pour but de montrer que le lien instance/constructeur n'est pas intuitif. Bien sûr, ça fonctionne en passant par le prototype ou l'opérateur instanceof, mais c'est typiquement un exemple de ce qui peut perturber les débutants.

    Et non, je n'ai pas traduit l'article "How to fix the class keyword" car j'étais en désaccord sur certains points et je n'aimais pas le ton de l'article trop agressif.
    One Web to rule them all

  8. #48
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Merci. Oui j'ai remonté car je cherche à comprendre ce sujet et ce qui tourne autour...

    Citation Envoyé par SylvainPV Voir le message

    L'héritage devient sans raison bien plus compliqué

    C'est là que la plupart des développeurs Java sont complètement largués. En suivant l'approche new, un héritage se ferait de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function Berline(constructor, model){
        Car.apply(this, arguments); //équivalent de super();
    }
     
    Berline.prototype = new Car(); // le modèle de la classe fils est une instance de la classe parente ???
     
    var volvo = new Berline("Volvo","S60");
    Alors j'ai fais quelques tests et j'ai remarqué que l'instruction Berline.prototype = new Car(); avec new faisait une chose qui ne me semble pas bonne (confirmez ou infirmez svp)... Si j'ai bien compris les étapes de new :

    1. Un nouvel objet est créé qui hérite de Car.prototype.
    ---> c'est comme si on faisait par exemple : var newObj = {}; newObj.__proto__ = Car.prototype; (ou bien ceci var newObj = Object.create(Car.prototype);)...

    Ça c'est ok c'est ce qu'on veut...

    2. La fonction constructrice Car est appelée avec les arguments fournis, this étant lié au nouvel objet créé.

    ---> Je pense c'est comme si on faisait Car.call(newObj);...

    Et c'est ça qui me semble une mauvaise chose car en faisant cela l'objet Berline.prototype aura pour propriétés propres : model, constructor et speed.

    Ce n'est peut-être pas grave mais cela me semble inutile...

    Du coup quand on fait : var volvo = new Berline("Volvo","S60");...

    L'objet volvo a pour propriétés propres : model, constructor et speed, ce qui est normal mais son prototype aura aussi ces trois propriétés ce qui me semble inutile...

    Est-ce qu'il n'y a pas là une consommation mémoire inutile ?

    ---> Alors je me demandais pourquoi ne pas combiner Object.create() avec les constructeurs et new en remplaçant Berline.prototype = new Car(); par Berline.prototype = Object.create(Car.prototype); ?

    Qu'en pensez-vous ? Est-ce que certains pratiquent cela ?

    Merci.

  9. #49
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Ton analyse est bonne, mais à moins que tu ais besoin de créer 50000 sous-catégories différentes pour Car, je ne pense pas que l'on ait à se soucier de ce surcoût de consommation mémoire Typiquement, ce qui occupera le plus de place en RAM, ce ne sont pas les prototypes mais les instances dérivées, et celles-ci devront nécessairement avoir leurs propriétés propres.

    Personnellement j'aime bien mettre des propriétés propres sur tous les objets, y compris les prototypes. Je trouve ça plus simple à raisonner d'un point de vue "prototype", le prototype étant censé être un objet bien réel lui aussi. Cela permet aussi de pouvoir lister les propriétés qui seront partagées par tous les objets créés à partir de ce prototype. Je trouverais ça bizarre que le prototype Car n'ait aucune propriété propre, et que le seul moyen de déduire les propriétés communes serait de lire le code du constructeur.
    One Web to rule them all

  10. #50
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Citation Envoyé par SylvainPV Voir le message
    Personnellement j'aime bien mettre des propriétés propres sur tous les objets, y compris les prototypes. Je trouve ça plus simple à raisonner d'un point de vue "prototype", le prototype étant censé être un objet bien réel lui aussi. Cela permet aussi de pouvoir lister les propriétés qui seront partagées par tous les objets créés à partir de ce prototype. Je trouverais ça bizarre que le prototype Car n'ait aucune propriété propre, et que le seul moyen de déduire les propriétés communes serait de lire le code du constructeur.
    Effectivement, pour le développement et la maintenance ça ajoute de la clarté, c’est une bonne chose.

    Citation Envoyé par SylvainPV Voir le message
    Typiquement, ce qui occupera le plus de place en RAM, ce ne sont pas les prototypes mais les instances dérivées, et celles-ci devront nécessairement avoir leurs propriétés propres.
    Pour compléter tes propos, il peut être utile de savoir que les propriétés du proto sont masquées (shadowed) dès qu’on affecte une valeur à une instance. À la première écriture, la propriété de l’instance est créée, elle est distincte de la propriété du prototype, et le moteur JS gère deux valeurs complètement indépendantes.

    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
    var proto = {
      machin: "chose",
      changeMachin() { this.machin = "truc"; }
    };
     
    var objA = Object.create(proto);
    console.log(objA.hasOwnProperty("machin")); // false
     
    objA.changeMachin();
    console.log(objA.hasOwnProperty("machin")); // true
     
    // en accédant directement à la propriété, même résultat :
     
    var objB = Object.create(proto);
    console.log(objB.hasOwnProperty("machin")); // false
     
    objB.machin = "bidule";
    console.log(objB.hasOwnProperty("machin")); // true
    On peut constater que la propriété existe toujours sur le proto et qu’elle n’a pas été modifiée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    console.log(objA.machin); // "truc"
    console.log(objA.__proto__.machin); // "chose"
    Ainsi les propriétés du proto sont rarement utilisées, et on peut se servir de ce fait pour repérer certains oublis de programmation. Si une propriété d’une instance a la même valeur que celle du proto, ça signifie qu’elle n’a pas été initialisée.

    Personnellement, je donne à mes prototypes des valeurs qui n’ont « pas de sens », par exemple NaN si la propriété est censée être un nombre, ou encore -1 si ça doit être un nombre positif.

    Ça permet également de donner un indice sur le type (type hint), qui peut être utile à la fois au développeur ou à la développeuse qui lit le code, et aux optimiseurs de demain qui, on peut l’imaginer, sauront en tirer parti.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  11. #51
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Merci à vous deux pour vos réponses...

    Alors si je comprends bien l’intérêt (avec Berline.prototype = new Car();) c'est la clarté, la visibilité, la facilité de la maintenance du code... Mais d'un point de vu fonctionnel ça n'apporte rien de plus ??? C'est-à-dire que les deux méthodes fonctionnent exactement de la même manière ? (Sauf peut-être qu'avec Berline.prototype = Object.create(Car.prototype); on consomme moins de mémoire et je pense aussi qu'elle est plus rapide puisque l'on a l’exécution de la fonction Car() en moins).

    Si j'ai bien compris avec new cela permet de savoir de quel constructeur proviennent les propriétés des instances (de Berline) mais comment vous faites concrètement ? Avec du code ou bien avec le débogueur (F12) ? Pour être clair, je reprends le code avec quelques modifications :

    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
    function Car(constructor, model) {
        this.model = model;
        this.constructor = constructor;
        this.speed = 0;
    }
     
    var golf = new Car("Volkswagen", "Golf");
    Car.prototype.strCar = "une string ajoutée à Car.prototype";
     
    function Berline(constructor, model) {
        Car.apply(this, arguments); //équivalent de super();
        this.colorBerline = "noir";
    }
     
    //Berline.prototype = new Car(); // le modèle de la classe fils est une instance de la classe parente ???
    Berline.prototype = Object.create(Car.prototype);
     
    var volvo = new Berline("Volvo", "S60");
    console.log(volvo); //

    Pour l'instance "volvo" j'obtiens ceci (à droite avec Berline.prototype = Object.create(Car.prototype); et à gauche avec Berline.prototype = new Car();) :



    On voit à gauche que l'objet volvo a pour propriétés propres : model, constructor et speed et que son proto a aussi ces trois propriétés ce qui permet de savoir que ces trois propriétés propres lui viennent du constructeur Car contrairement à la propriété "colorBerline", c'est bien ça l’intérêt ?

    Mais pour savoir ça ce n'est pas plus compliqué de jeter un oeil au constructeur Car (regarder tous les this.quelqueChose...), non ? En plus le débogueur nous permet d'aller voir ce constructeur en cliquant sur le lien à coté de [[FunctionLocation]].

    D'un point de vu fonctionnel les propriétés : model, constructor et speed du proto de volvo n'apportent rien, non ? Puisque ce ne sont pas ces propriétés-là qui seront utilisées (par exemple quand on fait volvo.speed, volvo.model ou volvo.constructor) mais les propriétés propres, n'est-ce pas ?

    En fait même si la consommation mémoire supplémentaire avec new n'est pas forcément énorme cela me semble étrange car on peut lire ici et là qu'un des intérêts d'ajouter des propriétés au prototype du constructeur (plutôt que d'utiliser des this.quelqueChose dans ce constructeur) c'était une consommation mémoire plus faible puisque ces propriétés seront communes à/partagées par toutes les instances...

    Cela avait été évoqué plus ou moins dans ce fil : Demande d'explication sur les prototypes

    Merci.

  12. #52
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Citation Envoyé par Watilin Voir le message
    Ainsi les propriétés du proto sont rarement utilisées, et on peut se servir de ce fait pour repérer certains oublis de programmation. Si une propriété d’une instance a la même valeur que celle du proto, ça signifie qu’elle n’a pas été initialisée.
    Ok mais par exemple regarde dans mon message précédent que la propriété "speed" est initialisée à 0 dans le constructeur Car du coup la propriété propre "speed" de volvo et la propriété "speed" du proto de volvo ont toutes les deux la valeur 0.

    Et si l'initiation se fait avec la valeur des arguments passés au constructeur alors si on oubli de le faire alors cela se verra, non ?


    Citation Envoyé par Watilin Voir le message
    Personnellement, je donne à mes prototypes des valeurs qui n’ont « pas de sens », par exemple NaN si la propriété est censée être un nombre, ou encore -1 si ça doit être un nombre positif.

    Ça permet également de donner un indice sur le type (type hint), qui peut être utile à la fois au développeur ou à la développeuse qui lit le code, et aux optimiseurs de demain qui, on peut l’imaginer, sauront en tirer parti.
    Ben il y a des outils comme ceux qui utilisent Tern qui sont capables de deviner le type d'une variable (en statique pas durant l’exécution) et pour aider ces outils (et les développeurs) on peut rajouter une JSDoc, non ? Il y a même un linter qui signale une erreur si on utilise un type qui ne correspond pas à la JSDoc (ici : #4 j'ai donné ce lien : Validation with JSDoc).

    Ou j'ai mal compris le problème ?

  13. #53
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Je crois que tu as déjà bien compris la différence entre les deux méthodes. Pour faire simple, équivaut à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Car.call(Object.create(Car.prototype), ...args)
    Je résume et reformule les deux arguments évoqués précédemment:
    1) la facilité à raisonner: le prototype est censé jouer le rôle de "modèle" pour les autres instances créées, c'est donc plus simple à se représenter si le prototype est construit de la même façon que les instances (donc avec la même fonction constructeur appelée), et s'il dispose des mêmes propriétés propres que les instances (afin d'être pleinement substituable à une instance)
    2) la réflectivité des propriétés communes: c'est intéressant de pouvoir déduire les propriétés communes d'objets dérivés d'un prototype en regardant directement dans le prototype avec Object.getOwnPropertyNames par exemple. Et il y a une grosse différence entre faire cette déduction par un développeur (en lisant un code) et l'obtenir directement de manière programmatique.

    En fait même si la consommation mémoire supplémentaire avec new n'est pas forcément énorme cela me semble étrange car on peut lire ici et là qu'un des intérêts d'ajouter des propriétés au prototype du constructeur (plutôt que d'utiliser des this.quelqueChose dans ce constructeur) c'était une consommation mémoire plus faible puisque ces propriétés seront communes à/partagées par toutes les instances...


    Bien sûr, hériter de la valeur du prototype permet d'économiser en mémoire, c'est d'ailleurs précisément ce à quoi servent les prototypes. Par exemple quand on veut des objets avec des méthodes en commun, on va les déclarer dans leur prototype pour éviter d'avoir X exemplaires de la même fonction en RAM. Mais ça n'a pas de sens d'hériter de tout, les objets ont nécessairement des propriétés propres sinon ils seraient tous identiques. Dans le cas présent, si on gère une liste de voitures, chaque voiture aura son propre modèle et son propre constructeur, cela n'a pas de sens de vouloir hériter cette valeur de la "voiture prototype". Par contre, Watlin suggère d'utiliser cette voiture prototype pour stocker des exemples / placeholders pour ces propriétés, comme par exemple { constructor: "Marque générique", model: "Modèle de base" }

    Identifier les propriétés propres ou héritées se fait généralement assez naturellement. Tu peux te poser la question: Qu'est-ce qui est propre aux voitures en général ? 4 roues, une méthode drive(). Qu'est-ce qui est propre à cette voiture là en particulier ? Un modèle, une couleur, des options...
    One Web to rule them all

  14. #54
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Pour les deux arguments, il faut que j'y réfléchisse encore et j'y reviendrais peut-être plus tard...

    Citation Envoyé par SylvainPV Voir le message
    Bien sûr, hériter de la valeur du prototype permet d'économiser en mémoire, c'est d'ailleurs précisément ce à quoi servent les prototypes. Par exemple quand on veut des objets avec des méthodes en commun, on va les déclarer dans leur prototype pour éviter d'avoir X exemplaires de la même fonction en RAM. Mais ça n'a pas de sens d'hériter de tout, les objets ont nécessairement des propriétés propres sinon ils seraient tous identiques. Dans le cas présent, si on gère une liste de voitures, chaque voiture aura son propre modèle et son propre constructeur, cela n'a pas de sens de vouloir hériter cette valeur de la "voiture prototype".
    Ben oui je suis d'accord "...les objets ont nécessairement des propriétés propres sinon ils seraient tous identiques..." et c'est le cas de volvo qui a entres autres pour propriétés propres : model, constructor et speed mais là où je bloque c'est pourquoi (d'un point de vu fonctionnel) son proto devrait aussi avoir ces trois propriétés... Et d'ailleurs les valeurs de ces trois propriétés du proto seront les mêmes pour toutes les instances de Berline, ce n'est donc pas ça qui va permettre de les distinguer, non ?

  15. #55
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Alors un truc intéressant, j'ai voulu voir ce qui se passe avec les class ES6 :

    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
    class Car {
        constructor(constructor, model) {
            this.model = model;
            this.constructor = constructor;
            this.speed = 0;
        }
     
        description() {
            console.log("model:", this.model);
        }
    }
    class Berline extends Car {
        constructor(constructor, model) {
            super(constructor, model);
            this.colorBerline = "noir";
        }    
    }
     
    var volvo = new Berline("Volvo", "S60");
    console.log(volvo);


    Regardez ce que j'obtiens pour volvo :



    On voit que l'objet volvo a entre autres pour propriétés propres : model, constructor et speed mais on ne les retrouve pas dans son proto...

    Cela correspond plus à ce que l'on obtient avec avec Berline.prototype = Object.create(Car.prototype); :

    Pour l'instance "volvo" j'obtiens ceci (à droite avec Berline.prototype = Object.create(Car.prototype); et à gauche avec Berline.prototype = new Car();) :

    Non ?

    Les class ES6 semblent proche d'une combinaison de Object.create() avec les constructeurs et new ??? Elles coupent la poire en deux par rapport au sujet du fil ?


    PS : A part que j'ai remplacé la string "strCar" par la méthode "description" car je ne sais pas comment ajouter des attributs/variables (string, nombre, tableau...) dans les class ES6...

  16. #56
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    L'opérateur class a déjà fait couler beaucoup d'encre. Il va dans la lignée de tout ce que j'ai décrié dans ce topic sur l'opérateur new: l'obligation d'un constructeur, l'écart par rapport à la nature prototypale etc. Pour distinguer propriétés propres et héritées, il a tordu sa syntaxe de manière à ce que l'on puisse déclarer les méthodes afin qu'elles se retrouvent dans le prototype, tandis que les autres propriétés sont assignées dans le constructeur et donc propres (même si une proposal pour les class fields est à l'étude). Même si c'est généralement adéquat et familier pour beaucoup, ça reste un choix arbitraire qui peut induire en erreur dans certains cas ; car il arrive qu'il soit pertinent qu'une fonction soit une propriété propre.
    One Web to rule them all

  17. #57
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Si j'ai bien compris avec new cela permet de savoir de quel constructeur proviennent les propriétés des instances (de Berline) mais comment vous faites concrètement ? Avec du code ou bien avec le débogueur (F12) ?
    Je ne comprends pas vraiment ta question, je crois que c’est un besoin que je n’ai jamais eu. Si tu organises bien ton code, tu sais toujours d’où vient ton objet. Dans le pire des cas, tu travailles avec du code tiers qui utilise massivement le polymorphisme ; mais dans ce cas, il est plus efficace de vérifier si un objet a quelque chose plutôt que s’il est quelque chose. C’est le duck typing : peu importe la forme du moment que ça fait le taf.

    Mais pour savoir ça ce n'est pas plus compliqué de jeter un oeil au constructeur Car (regarder tous les this.quelqueChose...), non ? En plus le débogueur nous permet d'aller voir ce constructeur en cliquant sur le lien à coté de [[FunctionLocation]].
    Je pense que c’est une question de préférence. Souvent dans un prototype on définit les méthodes, et comme les méthodes agissent sur les propriétés d’un objet, on a envie d’avoir ces propriétés sous les yeux. Suivant la façon dont on code, les propriétés peuvent être « plus proches » si on les a mises dans le constructeur ou dans le prototype.

    Citation Envoyé par Beginner. Voir le message
    Ok mais par exemple regarde dans mon message précédent que la propriété "speed" est initialisée à 0 dans le constructeur Car du coup la propriété propre "speed" de volvo et la propriété "speed" du proto de volvo ont toutes les deux la valeur 0.
    Le constructeur ne fait rien de plus qu’exécuter le code que tu écris dedans. Comme Sylvain l’a dit, c’est équivalent à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Car.call(Object.create(Car.prototype), ...args)
    En prose :
    1. le moteur crée une instance de Car en copiant les propriétés (ce qui inclut les méthodes) du prototype, c’est la partie .create() ;
    2. puis il lui applique le constructeur, avec les arguments que tu lui as passés, c’est la partie .call().


    Dans le constructeur, this référence l’instance fraîchement créée. (Sauf si tu oublies new ou si tu fais des trucs diaboliques avec call, apply ou bind.) Si tu attaches des propriétés à ce moment, ce seront des propriétés de l’instance, pas du prototype.

    Et si l'initiation se fait avec la valeur des arguments passés au constructeur alors si on oubli de le faire alors cela se verra, non ?
    Ça dépend. En l’occurence, tu n’as pas mis de garde-fou dans ton constructeur, et au moment où tu as appelé new Car() sans arguments, l’instance a reçu undefined comme valeurs pour constructor et pour model.

    Ben il y a des outils comme ceux qui utilisent Tern qui sont capables de deviner le type d'une variable (en statique pas durant l’exécution) et pour aider ces outils (et les développeurs) on peut rajouter une JSDoc, non ? Il y a même un linter qui signale une erreur si on utilise un type qui ne correspond pas à la JSDoc (ici : #4 j'ai donné ce lien : Validation with JSDoc).

    Ou j'ai mal compris le problème ?
    Non non c’est bien ça. Je n’utilise pas assez JSDoc

    Citation Envoyé par Beginner. Voir le message
    Les class ES6 semblent proche d'une combinaison de Object.create() avec les constructeurs et new ??? Elles coupent la poire en deux par rapport au sujet du fil ?
    Le fil à couper la poire en deux ? (pardon)
    Pas une combinaison vu qu’on a dit que Object.create et new étaient équivalents. Les class c’est pareil : ça change au niveau de la syntaxe, mais sous le capot rien de nouveau, c’est comme si tu avais défini un constructeur et un prototype. À la différence que, comme tu l’as constaté, on ne peut mettre que des méthodes sur le prototype. Et ça t’oblige à utiliser new. Bref, c’est plus limitant qu’autre chose…
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  18. #58
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Encore merci à vous deux pour vos réponses... Et aussi pour votre patience car il en faut...

    Citation Envoyé par Watilin Voir le message
    Le fil à couper la poire en deux ? (pardon)
    Je me suis mal exprimé, je ré-explique (en espérant ne pas trop vous saouler avec ce récapitulatif) : je voulais dire que j'ai cru comprendre que dans ce fil deux méthodes étaient discutées :

    1. Utiliser new avec des constructeurs.
    2. Utiliser Object.create.

    Alors je suis intervenu en gros en évoquant une troisième méthode : au lieu d'utiliser la méthode 1 pourquoi ne pas utiliser une combinaison des méthodes 1 & 2 ?

    Pour comparer la méthode 1 avec la méthode 3, j'ai repris le code de Sylvain avec quelques modifications :
    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
    function Car(constructor, model) {
        this.model = model;
        this.constructor = constructor;
        this.speed = 0;
    }
     
    var golf = new Car("Volkswagen", "Golf");
    Car.prototype.strCar = "une string ajoutée à Car.prototype";
     
    function Berline(constructor, model) {
        Car.apply(this, arguments); //équivalent de super();
        this.colorBerline = "noir";
    }
     
    //Berline.prototype = new Car(); // Pour la méthode 1
    Berline.prototype = Object.create(Car.prototype); // Pour la méthode 3
     
    var volvo = new Berline("Volvo", "S60");
    console.log(volvo); //
    C'est aux lignes 15 et 16 qu'on peut choisir* entre la méthode 1 et la méthode 3 (* en enlevant le commentaire de l'une des lignes pour le mettre à l'autre).

    Et alors j'ai présenté les résultats pour l'instance "volvo" (à droite (méthode 3) avec Berline.prototype = Object.create(Car.prototype); et à gauche (méthode 1) avec Berline.prototype = new Car();) :



    Je constate alors que dans les deux cas l'instance "volvo" a pour propriétés propres : model, constructor et speed et sur ce point c'est ok mais avec la méthode 1 on voit que le proto de volvo possède aussi ces trois propriétés on a donc une duplication de propriété dont je ne vois pas l’intérêt (d'un point de vu fonctionnel) puisque ce ne sont pas les propriétés du proto qui seront utilisées (par exemple quand on fait volvo.speed, volvo.model ou volvo.constructor) mais les propriétés propres...

    C'est pourquoi je me disais que la méthode 3 serait peut-être meilleure (consomme moins de mémoire et est peut-être plus rapide (étape 2 en moins cf.ci-dessous)) même si la différence n'est pas énorme...

    Et ensuite j'ai constaté qu'avec les class ES6 il n'y avait pas non plus cette duplication de propriété, les class ES6 serait plus proches de la méthode 3 ???

    Citation Envoyé par Watilin Voir le message
    Pas une combinaison vu qu’on a dit que Object.create et new étaient équivalents.
    Ben justement le test ré-expliqué ci-dessus + mon message #48 montrent qu'il y a une différence, mais on s'est peut-être mal compris...

    ---> Avec new on a l'étape n°2 en plus :

    Citation Envoyé par Beginner. Voir le message
    1. Un nouvel objet est créé qui hérite de Car.prototype.
    ---> c'est comme si on faisait par exemple : var newObj = {}; newObj.__proto__ = Car.prototype; (ou bien ceci var newObj = Object.create(Car.prototype);)...

    Ça c'est ok c'est ce qu'on veut...

    2. La fonction constructrice Car est appelée avec les arguments fournis, this étant lié au nouvel objet créé.

    ---> Je pense c'est comme si on faisait Car.call(newObj);...
    C'est d'ailleurs à cause de cette deuxième étape qu'on a une duplication des trois propriétés : model, constructor et speed.

    La méthode 3 évite cette deuxième étape et se contente de la première...

    -----------------------------
    Enfin bref...
    Ce n'est pas évident de s'y retrouver, il y a trop de possibilités (je pense aussi à tous les patterns qu'on voit dans les livres, tuto, articles...), je m'y perd...

  19. #59
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Honnêtement je pense que tu chipotes sur un point de détail, à savoir faut-il invoquer ou non le constructeur sur les prototypes intermédiaires. Concrètement, tu utilises toujours new et les constructeurs, et tous les arguments que j'ai présenté dans mon post initial s'appliquent toujours à ta méthode. Le plus gros atout de Object.create reste selon moi de pouvoir se débarrasser des constructeurs, et rien que ça simplifie énormément les choses et abrège fortement toute notre discussion précédente
    One Web to rule them all

  20. #60
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 872
    Points : 3 716
    Points
    3 716
    Par défaut
    Citation Envoyé par SylvainPV Voir le message
    Honnêtement je pense que tu chipotes sur un point de détail,...
    Ben non je ne chipote pas, tu crois ça car tu penses peut-être que je cherche une meilleure alternative à Object.create ou défendre "new + constructeurs" contre Object.create ou...

    Ben non ce n'est pas ça ---> Je voulais juste savoir pour quelqu'un qui veut utiliser new et les constructeurs, c'est-à-dire quelqu'un qui a fait un choix et qui sort donc du débat "seulement Object.create" Vs "new + constructeurs" alors est-ce que le mieux pour cette personne c'est d'utiliser la méthode 1 ou bien la méthode 3 ?

    C'était une vraie question...

    Quand on cherche à comprendre en profondeur on retourne les questions/sujets dans tous les sens... ça peut donner l'impression qu'on veut juste chipoter ben non pas toujours...

    Citation Envoyé par SylvainPV Voir le message
    Le plus gros atout de Object.create reste selon moi de pouvoir se débarrasser des constructeurs, et rien que ça simplifie énormément les choses et abrège fortement toute notre discussion précédente
    Ben oui mais pour un débutant c'est la jungle car après je voulais aborder la suite de ton fil, l'héritage avec Object.create, données privée...

    Mais sinon ce que j'aime bien dans les constructeurs ou les pattern ou les modules (je m'y perd donc je te laisse comprendre...) c'est par exemple que c'est facile d'initialiser des données simplement avec en passant des arguments, d'avoir des propriétés publics et privées... Je ne vois pas comment on fait ça juste avec Object.create...

    PS : Il y a justement un nouveau fil que je trouve intéressant car je me pose aussi ce genre de question (ça devrait être simple vu tous les livres, articles, tuto... Et ben non c'est le contraire c'est la jungle) : Analyse de 'Classes'...

Discussions similaires

  1. Surcharge de l'opérateur new
    Par :Bronsky: dans le forum C++
    Réponses: 17
    Dernier message: 27/10/2010, 22h33
  2. Grain de sel aléatoire, bonne ou mauvaise pratique ?
    Par Sergejack dans le forum Sécurité
    Réponses: 1
    Dernier message: 13/08/2009, 11h18
  3. Mauvaise pratique ? throw new exception()
    Par AsPrO dans le forum Langage
    Réponses: 4
    Dernier message: 24/04/2009, 12h36
  4. Redéfinition opérateurs new et delete globaux
    Par bolhrak dans le forum C++
    Réponses: 8
    Dernier message: 30/07/2007, 12h34
  5. namespace et opérateur new
    Par Sylvain Rousseau dans le forum C++
    Réponses: 3
    Dernier message: 07/01/2005, 00h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo