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 :

Optimisation POO et sécurité en JS


Sujet :

JavaScript

  1. #21
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 937
    Points
    22 937
    Billets dans le blog
    125
    Par défaut
    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() );
    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
        }
    });
    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.

  2. #22
    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
    Citation Envoyé par danielhagnoul Voir le message
    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.
    Autre option à plus court terme, passer à du Dart / TypeScript. Mais bon, on peut largement se débrouiller avec ES5 pour faire de la POO, si on accepte quelques concessions sur la syntaxe.

  3. #23
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 937
    Points
    22 937
    Billets dans le blog
    125
    Par défaut
    Pour le data-binding, type MVC (Angular aurait déjà testé et adopté) ou autre, il y a une nouvelle arme géniale : Object.observe( obj, callback );.

    Elle n'est pour l'instant utilisable que dans la dernière version de Chrome, mais il y a un "polyfil".

    Exemple basique, avec la dernière version de Chrome :

    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
    function log( change ) {
    	/*
       	* Note that |change.object| is actually a 
       	* reference to the target object.
       	*/
    	console.log( "What Changed? ", change.name );
    	console.log( "How did it change? ", change.type );
    	console.log( "What was the old value? ", change.oldValue );
    	console.log( "What is the present value? ", change.object[ change.name ] );
    }
     
    var Obj = {
    	"qui" : "Daniel",
    	"où" : "Belgique"
    };
     
    /*
    Object.observe( Obj, function( changes ){
    	changes.forEach( log );
    });
    */
     
    Object.observe( Obj, function( changes ){
    	changes.forEach( function( change ){
    		if ( change.type === "deleted" ){
    			console.log( "L'élément " + change.name + " de l'objet observé vient d'être détruit !" );
    		}
     
    		log( change );
    	});
    });
     
    Obj.qui = "Robert";
     
    Obj[ "où" ] = "France";
     
    delete Obj[ "où" ];
    Pour les anglophones :


  4. #24
    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
    C'est très intéressant, je pense m'en servir pour ma librairie de templating. Petite précision de terminologie, observe-js est un shim et non un polyfill (la lib a sa propre API constituant un niveau d'abstraction supplémentaire par rapport à Object.observe)

  5. #25
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    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 094
    Points : 6 755
    Points
    6 755
    Par défaut
    J'imagine que Proxy est un concurrent de observe dans la mesure où il ne fonctionne qu'avec Firefox

    Je l'ai découvert il a moins d'une semaine et je me suis un peu amusé avec. Par exemple, voici un objet qui ne génère jamais d'exception même quand on tente d'en appeler une méthode indéfinie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var proxy = new Proxy({}, {
        get: function( target, name ){
            return function( ){
                return "Did you call me " + name + "?";
            };
        }
    });
    @Daniel> Je n'ai pas bien compris pourquoi tu parles d'instanceof à propos d'ES5. L'opérateur instanceof date de JavaScript 1.4, et même avec de l'héritage « à l'ancienne », il reconnaît les classes parentes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function A(){}
    function B(){}
     
    // B hérite de A
    B.prototype = new A();
     
    var b = new B();
    console.log(b instanceof B); // true
    console.log(b instanceof A); // true aussi

  6. #26
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 937
    Points
    22 937
    Billets dans le blog
    125
    Par défaut
    Bonsoir

    Correction du second exemple du tutoriel : http://weblog.bocoup.com/javascript-object-observe/

    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
    <!DOCTYPE html>
    <html lang="fr" dir="ltr">
    <head>
    	<meta charset="utf-8">
    	<meta name="viewport" content="initial-scale=1.0">
    	<meta name="author" content="Daniel Hagnoul">
    	<title>Forum jQuery</title>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/headjs/0.99/head.min.js"></script>
    	<script>
    		"use strict";
     
    		head.js( 
    			"http://d3js.org/d3.v3.min.js",
    			//"http://code.jquery.com/jquery-2.0.3.min.js",
    			"http://code.jquery.com/jquery-2.1.0-beta2.js",
    			"http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/i18n/jquery-ui-i18n.min.js",
    			"http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js",
    			"http://danielhagnoul.developpez.com/lib/dvjh/d3aBase.js", function(){
     
    $( function(){	
     
    });
     
    $( window ).load( function(){
     
    	/*
    	 * On peut personnaliser la notification envoyée par Object.observe() 
    	 * en l'interceptant avec Object.getNotifier et en la relançant avec 
    	 * la méthode notify() qui contiendra un objet anonyme adapté à nos besoins.
    	 * 
    	 * Il ne faut pas oublier de passer à Object.observe, en troisième paramètre, 
    	 * un array contenant les event.type surveillés, sinon les types personnels 
    	 * ne sont pas reconnus. 
    	 */
     
    	( function( exports ){
     
    		function log( change ){
    			console.log( "\n\nObserved..." );
     
    			/*
    			 * DANGER !
    			 * 
    			 * Pour le type "read", on déclenchera une 
    			 * récursion infinie si on lit la valeur
    			 * d'une propriété de l'objet.
    			 */
     
    			if ( change.type === "read" ){
    				console.log( "What was accessed ? ", change.name );
    				console.log( "How did it change ? ", change.type );
    				console.log( "What value was given ? ", change.oldValue );
    			} else {
    				console.log( "What Changed ? ", change.name );
    				console.log( "How did it change ? ", change.type );
    				console.log( "What was the old value ? ", change.oldValue );
    				console.log( "What is the present value ? ", change.object[ change.name ] );
    			}
    		}
     
    		var priv = new WeakMap();
     
    		function User( name ){
    			this.name = name;
     
    			priv.set( this, {
    				"login" : Date.now(),
    				"lastSeen" : Date.now()
    			});
     
    			Object.defineProperties( this, {
    				"seen" : {
    					"set" : function( val ){
    						var notifier = Object.getNotifier( this ),
    							p = priv.get( this );
     
    						notifier.notify({
    							"type" : "updated",
    							"name" : "seen",
    							"oldValue" : p.lastSeen
    						});
     
    						p.lastSeen = val;
    						priv.set( this, p );
    					},
    					"get" : function(){
    						var notifier = Object.getNotifier( this ),
    							p = priv.get( this );
     
    						notifier.notify({
    							"type" : "read", // type personnel
    							"name" : "seen",
    							"oldValue" : p.lastSeen
    						});
     
    						return p.lastSeen;
    					}
    				}
    			});
     
    			Object.observe( this, function( changes ){
    				changes.forEach( log );
    			}, [ "updated", "read" ] );
     
    		}		
     
    		exports.User = User;
     
    	}( window ));
     
    	var ObjUser = new User( "Rick" );
     
    	// event type read
    	// ISOformat() est une méthode d3.js, voir le code du fichier d3aBase.js
    	console.log( "read, new Date( ObjUser.seen = ", ISOformat( new Date( ObjUser.seen ) ) );
     
    	// event type updated + read
    	ObjUser.seen = $.now();
     
    	// event type read
    	var data = ObjUser.seen;
     
    });
     
    		});
    	</script>
    	<link href='http://fonts.googleapis.com/css?family=Sofia|Ubuntu:400|Kreon'>
    	<link rel="stylesheet" href="http://danielhagnoul.developpez.com/styles/dvjhRemBase.css">
    	<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/sunny/jquery-ui.min.css">
    	<style>
    		/* TEST -- Nota bene : ici 1 rem est égal à 10 px, voir dvjhRemBase.css */
     
     
    	</style>
    </head>
    <body>
    	<header>
    		<hgroup>
    			<h1>Forum jQuery</h1>
    			<h2>
    				<a href="">Lien</a>
    			</h2>
    		</hgroup>
    	</header>
    	<section class="conteneur">
     
    	</section>
    	<footer itemscope itemtype="http://danielhagnoul.developpez.com/">
    		<time datetime="2013-11-18T01:36:49.688+0100" pubdate>2013-11-18T01:36:49.688+0100</time>
    		<span itemprop="name">Daniel Hagnoul</span>
    		<a href="http://www.developpez.net/forums/u285162/danielhagnoul/" itemprop="url">@danielhagnoul</a>
    		<a href="http://danielhagnoul.developpez.com/" itemprop="url">Mon cahier d’exercices</a>
    		<a href="http://javascript.developpez.com/faq/jquery/" itemprop="url">FAQ</a>
    		<a href="http://javascript.developpez.com/cours/?page=frameworks#jquery" itemprop="url">Tutoriels</a>
    	</footer>
    </body>
    </html>

  7. #27
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    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 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Hmm ce n'est pas ce qu'il m'a semblé. Tu n'as pas lié la même page que moi

    Cela dit, sans avoir regardé de près, j'ai l'impression qu'Object.observe est une revisitation du (très) vieil Object.watch, les performances en plus. Si c'est ça, c'est une bonne nouvelle. Je vais étudier la chose

  8. #28
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 937
    Points
    22 937
    Billets dans le blog
    125
    Par défaut
    Citation Envoyé par Watilin Voir le message
    [...] Cela dit, sans avoir regardé de près, j'ai l'impression qu'Object.observe est une revisitation du (très) vieil Object.watch, les performances en plus. Si c'est ça, c'est une bonne nouvelle. Je vais étudier la chose
    C'est bien cela !

    Les Proxies sont des objets pour lesquels le programmeur doit définir la sémantique en JavaScript. Les Proxies permettent au programmeur de définir complètement le comportement d'un objet. Ils sont capables de fournir une API métaprogrammation.

  9. #29
    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
    Proxy et Object.observe sont deux propositions pour ES6 (harmony). On ne sait pas encore laquelle sera retenue, peut-être les deux, peut-être une complètement différente. Dans tous les cas on ne peut s'en servir pour le moment qu'à titre expérimental.

  10. #30
    Membre émérite
    Avatar de Kaamo
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    1 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 165
    Points : 2 778
    Points
    2 778
    Par défaut
    Je dérive aussi du sujet mais ... voici une mise en application des proxies : Gérer les indices négatifs dans les tableaux (comprendre si je veux l'indice -1 d'un Array, ça retourne le dernier indice du tableau)

    D'ailleurs je croyais que l'API Proxy avait remporté la bataille sur Object.observe

  11. #31
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 71
    Points : 54
    Points
    54
    Par défaut
    Citation Envoyé par Kaamo Voir le message
    Je dérive aussi du sujet mais ...
    J'ai ouvert ce poste pour comprendre le potentiel de javascript. Vos réponses ne sont pas des "dérives", ce sont des mines de connaissances.

    Si d'autres novices lisent ce thread, voici un article que j'ai beaucoup aimé. Il traite des différentes formes d'héritage possible en javascript et cite quelles bibliothèques utilisent quelles méthodes :
    http://www.piprime.fr/1495/tout-savo...ge-javascript/

  12. #32
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    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 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Eh bien voilà qui a servi à quelqu'un puisque la page que tu as liée parle d'un très célèbre article de Douglas Corckford que… Je n'avais jamais lu "^^. Et que j'ai trouvé très intéressant. Je comprends maintenant l'intérêt de Object.create : faire hériter les objets les uns des autres sans utiliser de constructeur.

  13. #33
    Membre émérite
    Avatar de Kaamo
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    1 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 165
    Points : 2 778
    Points
    2 778
    Par défaut
    très célèbre article de Douglas Corckford que… Je n'avais jamais lu "^^
    Sacrilège !
    Je mets en exergue la puissance de Object.create dans le dernier post de la première page.

    Mais bientôt, tout ça sera de l'histoire ancienne avec l'arrivée de la norme ES6 et des "vraies" classes.

  14. #34
    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 ne me réjouis pas de l'arrivée des classes en ES6, au contraire. On ne me fera pas croire qu'un langage peut évoluer en changeant de paradigme tout en restant rétrocompatible. Si un développeur préfère manipuler les classes tandis qu'un autre sur le même projet préfère les prototypes, ça risque de vite devenir un sacré bazar. On voit ce que ça a donné avec l'opérateur new.

    Il suffirait d'ajouter quelques fonctions utiles pour faire de la POO par prototype, comme Object.prototype.extend(parent), pour pouvoir enfin faire un vrai héritage sans se prendre la tête. Mais non, on reproduit les erreurs du passé...
    Citation Envoyé par Douglas Crockford
    This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript. JavaScript's constructor pattern did not appeal to the classical crowd. It also obscured JavaScript's true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.
    Encore une fois le langage se plie à la majorité, on le tord et on le retord pour qu'il colle aux enseignements classiques de la POO. Sauf que ça ne colle pas. Comment va-t-on expliquer aux devs Java qu'en JS, les classes sont des objets ? Ou qu'une instance peut changer de classe dynamiquement ?

  15. #35
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    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 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Bon attention, ce que je vais dire est à prendre avec des pincettes. C'est une réflexion qui vient juste de m'arriver à l'esprit.

    En fait, si on allait radicalement dans le sens d'un JavaScript tout-prototype, on abandonnerait l'idée d'introduire des classes, et on pourrait même aller jusqu'à déverrouiller les mots-clés liés à ce concept (class, extends, etc.) qui auraient alors un sens tout à fait banal et pourraient être utilisés comme noms de variables (même si c'est pas forcément une bonne idée).

  16. #36
    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 suis parfaitement d'accord, et libérer class et extends serait une bonne chose, pour désigner l'attribut HTML class et les valeurs utilisées par des fonctions comme $.extend. Malheureusement, on ne changera pas les standards

  17. #37
    Membre émérite
    Avatar de Kaamo
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    1 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 165
    Points : 2 778
    Points
    2 778
    Par défaut
    Il suffirait d'ajouter quelques fonctions utiles pour faire de la POO par prototype, comme Object.prototype.extend(parent), pour pouvoir enfin faire un vrai héritage sans se prendre la tête. Mais non, on reproduit les erreurs du passé...
    Je suis bien d'accord avec toi aussi. Il n'y aurait jamais du avoir de pseudo-classe camouflée derrière une fonction qui instancie des objets avec new car elle a un constructor ?!?
    Quand j'ai appris JavaScript, j'ai eu du mal à me faire à cette idée, on dirait un truc qui pendouille par dessus le langage pour faire comme les autres.

    Mais ... je crois que les class ES6 ne seront que du sucre syntaxique pour enfin arrêter la confusion entre les fonctions 'classiques' (tu me passes des arguments, je te retourne une valeur) des fonctions ayant un rôle de constructeur d'instance.

    En gros, si j'ai bien compris la norme :

    Ce code ES5 :
    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
    function Animal(name) {
      this.name = name || 'inconnu';
    }
    Animal.prototype.presenter = function () {
      return "Animal " + this.name;
    };
     
    function Ours(name) {
      Animal.call(this, name);
      this.cri  = 'WWWWOOOOOAAAR';
    }
    Ours.prototype = Object.create(Animal.prototype);
    Ours.prototype.constructor = Ours;
    Ours.prototype.crier = function () {
      return Animal.prototype.presenter.call(this) + " et je crie : " + this.cri;
    };

    Équivaut à peu près (super d'ES6 n'est pas facile à simuler exactement) en 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
    class Animal {
      constructor(name) {
        this.name = name || 'inconnu';
      }
      presenter() {
        return "Animal " + this.name;
      }
    }
     
    class Ours extends Animal {
      constructor(name) {
        super.constructor(name);
        this.cri = 'WWWWOOOOOAAAR';
      }
      crier() {
        return super.presenter() + " et je crie : " + this.cri;
      }
    }

    Du coup, le new aura tout son sens en ES6 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var ours1 = new Ours('Baloo');
    ours1.crier(); // "Animal Baloo et je crie : WWWWOOOOOAAAR"
    ours1.presenter(); // "Animal Baloo"
    Si ça permet d'éviter les confusions et d'apprendre plus simplement, je suis plutôt pour.
    Par contre, quid des objets créés .. est-ce que les prototype sont bien utilisés, je ne sais pas. J'espère.

  18. #38
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    1 616
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 616
    Points : 3 966
    Points
    3 966
    Par défaut
    Ca fait plaisir de lire ça Sylvain, j'ai failli réagir dans ce sens hier.

    Ca tourne à l'obsessionnel ces histoires de classes pour certains, ce n'est pas du tout à toi que je pense kaamo.

    j'avais lu un article ancien et intéressant :
    http://steve-yegge.blogspot.fr/2006/...-of-nouns.html

    aujourd'hui la programmation fonctionnelle semble connaître des regains d'intérêt, à juste titre je crois, et l'ECMAscript, le JS est particulièrement bien doté de ce point de vue.

    Quand aux programmeurs java... je ne crois pas beaucoup d'entre eux capables de considérer le JS d'abord, et ensuite avoir le recul nécessaire pour en saisir la puissance.

    Java, C++, C# fonctionnent comme des églises, avec des processus de dévotion très marqués pour qui n'est pas dans le trip

  19. #39
    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
    Mais ... je crois que les class ES6 ne seront que du sucre syntaxique pour enfin arrêter la confusion entre les fonctions 'classiques' (tu me passes des arguments, je te retourne une valeur) des fonctions ayant un rôle de constructeur d'instance.
    Ce n'est pas là la vraie confusion. Le principe d'avoir un rôle de "constructeur d'instance" est déjà un indice de confusion avec la POO par classes. C'est d'ailleurs pour ça qu'on utilise des fonctions pour faire les simili-classes en JS, afin de retrouver un constructeur.

    POO: on manipule plusieurs objets basés sur un même modèle
    POO classes : on manipule plusieurs instances d'une même classe
    POO prototype : on manipule plusieurs objets partageant un même prototype

    Nulle question ici de constructeurs ou de fonctions. On devrait simplement pouvoir faire : "déclare moi un nouvel objet avec ce prototype, puis donne-lui ces propriétés". Mais aucune des syntaxes existantes ne permet de faire simplement ça, on se tape forcément des fonctions à cause des mots-clés comme new, instanceof, constructor etc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var Animal = {
        crier: function(){ return this.cri; }
    };
     
    var ours = Object.create(Animal);
    ours.cri= 'WWWWOOOOOAAAR';
    var oiseau = Object.create(Animal);
    oiseau.cri = 'cuicui';
     
    console.log(ours.crier()); //WWWWOOOOOAAAR
    console.log(oiseau.crier()); //cuicui
    console.log(oiseau instanceof Animal); //Uncaught TypeError: Expecting a function in instanceof check, but got #<Object>
    De plus le prototype d'un objet n'est pas accessible en écriture alors que ça devrait être l'un des avantages principaux de la POO prototype. On peut bricoler un peu avec __proto__, mais ça ne fait pas partie du standard.

    edit : j'ai retrouvé des fonctions que j'avais oublié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    console.log(Animal.isPrototypeOf(ours)); //true
    console.log(Object.getPrototypeOf(oiseau) === Animal); //true
    Bon, c'est déjà ça... reste à mettre de côté toutes les notions dérivées de la POO par classes intégrées au JS, ce qui n'est pas chose facile...

Discussions similaires

  1. Réponses: 13
    Dernier message: 11/07/2011, 06h17
  2. Réponses: 1
    Dernier message: 16/12/2006, 01h27
  3. [POO Optimisation] Règles d'écriture d'un site PHP
    Par KiLVaiDeN dans le forum Langage
    Réponses: 19
    Dernier message: 30/09/2006, 02h08
  4. [Sécurité] Conseils sécurité et optimisation
    Par cyrill.gremaud dans le forum Langage
    Réponses: 2
    Dernier message: 20/06/2006, 00h51
  5. Réponses: 6
    Dernier message: 28/07/2005, 22h14

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