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 :

OOP et javascript : proto ou pas proto ?


Sujet :

JavaScript

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 35
    Points : 28
    Points
    28
    Par défaut OOP et javascript : proto ou pas proto ?
    Bonjour, après des années passées à utiliser les frameworks existants j'essai de revenir à l'essentiel pour une meilleure compréhension.

    En premier lieu je cherche à transposer mes connaissances de l'OO vers javascript à l'aide d'un bouquin (jS, gardez le meilleur de Douglas Crockford).

    Bon, bref. J'ai bien compris qu'il n'y a pas de notion de classe en JS et que tout est objet. Je vois aussi à quoi sert le prototype.

    Par contre, j'ai fait un petit test et il y a un truc qui m'échappe.

    Quelle est la différence entre les méthodes dosomething et sogood ??
    A l’exécution j'obtiens exactement le même comportement (attendu). Dans ce cas, pourquoi devrais-je utiliser une déclaration par prototype ?

    Merci d'avance


    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
     
    var Player = function (name) {
        this.name = name;
        this.dosomething = function(arg) {
            console.log(this.name + ' here with ' + arg);
        }
    }
     
    Player.prototype.sogood = function(arg) {
        console.log(this.name + ' here proto with ' + arg);
    }
     
    var p1 = new Player('bodo');
    p1.dosomething('toto');
    p1.sogood('toto');
    Ah puis, tant qu'on y est - quelle est la différence entre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var Player = function (name) {
    }
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var Player = function Player(name) {
    }

  2. #2
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    Pour ta première question, il existera toujours UNE et UNE seule instance de la fonction "sogood".

    Tandis que la fonction dosomething ne sera déclaré que lorsqu'un objet sera instancié et sera propre à cet objet, c'est à dire qu'il existera une fonction "dosomething" pour chaque objet instancié.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ex:
    var p1 = new Player('bodo1');
    var p2 = new Player('bodo2');
    if( p1.dosomething == p2.dosomething ){
     // FALSE
    }
    if( p1.sogood == p2.sogood ){ 
     // TRUE
    }
    ne pas dupliquer une fonction (avec les prototypes) permet notament d'épargner pas mal de placer et d'exécution lors que tu crées des quantités conséquentes d'objets.

    tu peux tester si une fonction (ou attribut) est propre à un objet grace à la méthode "hasOwnProperty"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    p1.hasOwnProperty('sogood'); // false
    l'avantage de redéclarer une méthode à l'intérieur de l'objet peut par exemple être utile pour accèder à des champs privés comme les getters.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Player(name){
        var _name = name;
        this.getName = function(){
            return _name;
        };
    }
    Player.prototype.getNameProto = function(){
        return _name; // ne fonctionnera pas
    };
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  3. #3
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Points : 91 418
    Points
    91 418
    Billets dans le blog
    20
    Par défaut
    Dans ce cas, pourquoi devrais-je utiliser une déclaration par prototype ?
    Tout simplement pour des questions entre autre de performances.
    Lorsque tu déclares la méthode dans le constructeur, chaque instance de l'objet que tu vas créer va définir sa propre méthode, alors que si tu la déclares dans le prototype, chaque instance héritera de la même définition.
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  4. #4
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    Citation Envoyé par Paganoni Voir le message
    Ah puis, tant qu'on y est - quelle est la différence entre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var Player = function (name) {
    }
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var Player = function Player(name) {
    }
    le 2ème exemple n'existe pas vraiment (sauf erreur de codeur) car ça revient au même que de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function Player(name){}
    maintenant la différence entre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function Player(){}
    et 
    Player = function(){};
    est que dans le 2ème cas il s'agissent d'une fonction anonyme assigné à la variable "Player". (enfin au pointeur, vu que tout les objets et fonctions se joue avec des pointeurs en javascript.)

    dans le premier cas, il s'agit d'une fonction nommée qui se également pointé par la variable "Player".

    en gros, les 2 façons de faire se valent et son (quasi) équivalentes. les deux sont en général autant utilisés. même si la function nommée permet (sous chrome et firefox mais pas IE) de renvoyer le nom de la fonction via l'attribut "name". ex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function b(){};
    var maFonction = b;
    alert(maFonction.name); // b
     
    var b = function(){};
    var maFonction = b;
    alert(maFonction.name); // ... null ou undefined (je sais plus ^^)
    en bref, ça dépendra surtout de tes habitudes si tu préfères d'avoir voir "function" ou le nom de la fonction.

    aussi si tu as l'habitude de coder dans des objets, tu auras plus tendances à utiliser l'assignation je pense, par habitude. ex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var obj = {
      alpha : function(){},
      beta : function(){},
      num : 5,
      text : "blabla"
    };
    enfin, dernière anecdote, le point-virgule n'est pas nécessaire à la fin de la déclaration d'une fonction tandis qu'il est obligatoire après une assignation. il est donc souvent oublié quand on débute en javascript et est source d'erreur. ex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function alpha(){}/*pas besoin de ; ici*/alpha();

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var alpha = function(){};/*besoin du ; ici pour clore l'assignation*/alpha();
    voila, cet énorme texte pour dire que les 2 reviennent exactement au même.
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 35
    Points : 28
    Points
    28
    Par défaut
    Rha bin c'est bien sûr !

    Merci beaucoup pour vos éclaircissements !

  6. #6
    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 Willpower Voir le message
    le 2ème exemple n'existe pas vraiment (sauf erreur de codeur)
    Si si, ça existe, et non non ce n'est pas une erreur C'est même très utile car le nom de la fonction apparaît dans la pile d'appel quand on fait du debug.

    Un exemple tout simple :
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <input type="button" id="bouton1" value="1" />
    <input type="button" id="bouton2" value="2" />
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    document.getElementById('bouton1').addEventListener(
    	'click', function() { // fonction anonyme
    		var x;
    		x.flute = 'oups';
    	}, false);
    document.getElementById('bouton2').addEventListener(
    	'click', function Hareng() { // fonction nommée
    		var x;
    		x.reponse = 42;
    	}, false);
    Avec Firebug, j'obtiens ceci quand je clique sur « 1 » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    x is undefined
    (?)()
    x.flute = 'oups';
    et ceci quand je clique sur « 2 » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    x is undefined
    Hareng()
    x.reponse = 42;
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  7. #7
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    en fait, je parlais de nommer la fonction et de réassigner la fonction dans elle-même :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var NOM = function NOM(){};
    qui n'avait aucun sens et qui revenait à faire tout simplement :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  8. #8
    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
    Ah oui, là je suis d'accord, ça revient exactement au même
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 128
    Points : 210
    Points
    210
    Par défaut
    Non ça ne revient pas vraiment au même.

    L'une est une expression et l'autre est une déclaration, ce qui veut dire que les deux ne sont pas évaluées au même moment.

    La déclaration sera évaluée (elle ainsi que les autres déclarations qu'elle contient) à l'entrée du contexte), l'expression sera évaluée à l'execution.

    Cela peut avoir son importance en cas d'évaluation tardive (lazy init) ou de branchement de code. Si les invariantes à initialiser sont couteuse, très rarement utilisées ou si l'on veut implémenter un Strategy Pattern, il peut être utile de maitriser ces subtilités.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // ici casCritique sera initialisé quoi qu'il arrive, même si l'on ne s'en sert jamais
     
    if(uneChanceSurUnMilliard === true){
        function casCritique(){
            // initialisation complexe très couteuse
        }
    }
    else{
        // NOOP
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // ici casCritique (enfin, la valeur de la variable casCritique pour être exact) sera initialisé une fois sur un milliard
     
    if(uneChanceSurUnMilliard === true){
        var casCritique = function casCritique(){
            // initialisation complexe très couteuse
        }
    }
    else{
        // NOOP
    }
    Bon après dans la pratique 99% du temps, OSEF.

  10. #10
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    Clap Clap Clap.

    Tu viens de m'apprendre qqe chose que je ne connaissais mais ABSOLUMENT pas en javascript.

    Je viens donc de lire un excellent article à ce sujet : http://kangax.github.com/nfe/


    Donc comme tu le dis, ce n'est pas du tout pareil car :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    try{alpha(); }
    catch(e){alert("error: alpha");}
    function alpha(){alert(' exec alpha');}
    ne provoquera pas d'erreur.

    tandis que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    try{alpha(); }
    catch(e){alert("error: alpha");}
    var alpha = function alpha(){alert(' exec alpha');}
    en provoquera.





    edit:
    Un autre exemple impressionant donné dans l'article :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // Never do this!
    // Some browsers will declare `foo` as the one returning 'first', 
    // while others — returning 'second'
    if(true) {
      function foo() {
        return 'first';
      }
    }
    else {
      function foo() {
        return 'second';
      }
    }
    alert(foo());
    sous chrome, j'ai bien "second" qui s'affiche.
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  11. #11
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    je m'amuse comme un fou depuis qqes minutes avec ça, en fait ça peut avoir des conséquence effroyable pour ceux qui travaillent à plusieurs sur un gros projet sans savoir ce qui précède. (par exemple si chaque partie peut écrasser toutes les variables précédentes .. surtout une variable nommé "tmp" par exemple)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // CODE INCONNU PRECEDENT
    var tmp = function(){alert('piège');};
     
    // CODE EN COURS ..
    function tmp(){alert('tmp');};
    // affichera "piège"
    tmp();

    ou plus tordu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // CODE INCONNU PRECEDENT
    var tmp = (function(tmp){return function(){tmp();};})(tmp);
     
    // CODE EN COURS ..
    function tmp(){alert(arguments.callee == tmp);};
    // affichera "false"
    tmp();


    edit: en version plus extrême pour surcharger une méthode qui n'existe pas encore (enfin je veux dire qui se trouve en tout début de code) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // CODE INCONNU PRECEDENT
    var tmp = (function(tmp){return function(){tmp.apply(this,arguments);};})(tmp);
     
    // CODE EN COURS ..
    var code = Math.random();
    function tmp(c){ if(c==code) alert(arguments.callee == tmp);};
    // affichera "false"
    tmp(code);
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 128
    Points : 210
    Points
    210
    Par défaut
    Huhum, je vois que tu es allé puiser l'information directement à la meilleure source.

    Les articles de kangax sont effectivement la référence absolue sur ce sujet.

    Si cela t'intéresse tant que ça je te conseille la génialissime série d'articles "ECMA-262-3 in detail" de Dmitry Soshnikov.
    Notamment les deux premiers chapitres qui expliquent toutes les bases et mécanisme internes à l'origine de ces subtilités :
    http://dmitrysoshnikov.com/ecmascrip...tion-contexts/

    Dans un autre registre tu as aussi cet autre article de kangax qui explique quelques différences entre les variables et les propriétés selon les types de contextes d'execution. (je te conseille de lire préalablement les deux premiers chapitres de soshnikov pour bien tout comprendre, mais tu peux faire sans).

    http://perfectionkills.com/understanding-delete/

  13. #13
    Inactif  

    Profil pro
    Inscrit en
    Mai 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 345
    Points : 496
    Points
    496
    Par défaut
    Et sinon le très bon javascript.info a un article dessus :
    http://javascript.info/tutorial/func...nd-expressions

  14. #14
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    je suis devenu accro


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // hook all declarations
    (function(f,i){for(i in window)
    if("sessionStorage"!=i && typeof (f=window[i]) == 'function' && !f.toString().match(/\[native code\]/) )
    window[i] = (function(f,n){return function(){alert(n+' hooked');f.apply(this,arguments);};})(f,i);})();
     
    // test code here
    function alpha(){
    	document.write('alpha<br/>');
    }
    alpha();
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

Discussions similaires

  1. [XSLT]javascript ne marche pas dans le XSL
    Par KorT3XX dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 20/06/2007, 13h10
  2. [javascript] Ne fonctionne pas sur Safari
    Par sanosuke85 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 12/03/2007, 09h20
  3. [AJAX] Javascript n'est pas exécuté avec ajax.
    Par John6281 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 27/02/2007, 14h35
  4. Javascript-html: ne pas afficher le javascript:void(0)
    Par Anarianthe dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 01/02/2006, 23h32
  5. [Javascript] ne fontionne pas ?
    Par MatMeuh dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 15/10/2004, 15h21

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