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 :

Objet literal ou prototype


Sujet :

JavaScript

  1. #1
    Membre confirmé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Points : 637
    Points
    637
    Par défaut Objet literal ou prototype
    Bonjour,
    toujours dans ma recherche de bonne pratique je voulais savoir ce que vous pensiez vis a vis de la maniere de construire des objets en Javascript.

    Prototype
    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
     function Person(name) {
            this.name = name;
        }
     
        Person.prototype.get_name = function() {
            return this.name;
        };
     
        Person.prototype.set_name = function(name) {
            this.name = name;
        };
     
        Person.prototype.set_name1 = function(name) {
            this.name = name;
        };
     
        Person.prototype.set_name2 = function(name) {
            this.name = name;
        };
     
        Person.prototype.set_name3 = function(name) {
            this.name = name;
        };
     
        Person.prototype.set_name4 = function(name) {
            this.name = name;
        };
     
        Person.prototype.set_name5 = function(name) {
            this.name = name;
        };
    Ou Literal
    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
    var person = function(pname) {
            return {
                    'get_name': function() {
                            return pname;
                    },
                    'set_name': function(name) {
                            pname = name;
                    },
                    'set_name1': function(name) {
                            pname = name;
                    },
                    'set_name2': function(name) {
                            pname = name;
                    },
                    'set_name3': function(name) {
                            pname = name;
                    },
                    'set_name4': function(name) {
                            pname = name;
                    },
                    'set_name5': function(name) {
                            pname = name;
                    }
            };
        };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      var _p = new Person('John');
        var _c = person('John');
    Merci pour votre experience
    MCTS Microsoft.
    La conception : Prendre le temps pour gagner du temps.

  2. #2
    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
    Les objets partagent les méthodes et propriétés de leurs prototypes.
    Dans le premier exemple, new Person() construit un objet Person et récupère les méthodes déclarées dans Person.prototype.
    Tandis qu'avec la seconde méthode, person() renvoie un objet Object contenant les différentes méthodes. Chaque objet créé possède ses propres déclarations de ces fonctions, comme un tas de singletons en quelque-sorte.

    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
    function Person(name){        
        this.name = name;
    }
     
    Person.prototype.get_name = function() {
      return this.name;
     };
     
    var person = function(pname) {
            return {
                    'get_name': function() {
                            return pname;
                    }
            };
        };
     
    var a = new Person('John');
     
    var b = new Person('Jack');
     
    var c = person('Jim');
     
    var d = person('Jeff');
     
    console.log(person.get_name); //undefined
    console.log(c.get_name()); // Jim
     
    Person.prototype.get_name = function(){ return "My name is "+this.name; };
    a.get_name(); //My name is John
    b.get_name(); //My name is Jack
    One Web to rule them all

  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
    Ta question n'a pas de sens parce que tu essayes d'opposer deux concepts qui n'ont rien à voir...
    Donc avant les bonnes pratiques, ce sont surtout les fondamentaux qu'il faut approfondir.

    La notion de littéral s'oppose habituellement à celle de constructeur pour créer un type natif de JavaScript. Exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var bool = false;  // Littéral booléen
    var bool = new Boolean(true); // Constructeur
    var nb = 5; // Littéral
    var nb = new Number(5); // Constructeur
    var st = 'toto';
    var st = new String('toto');
    var tab = [];
    var tab = new Array();
    var obj = {};
    var obj = new Obect();
    Dans tes exemples, tu confonds aussi un constructeur avec une fonction renvoyant un objet.
    Donc dans le premier cas, tu fais de la POO, pas dans le second.

    Enfin, quant à l'utilisation de l'un ou de l'autre, cela dépend de l'utilisation que tu en as.
    En général, un constructeur n'a d'utilité que si l'on est susceptible d'en utiliser plusieurs instances.
    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 confirmé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Points : 637
    Points
    637
    Par défaut
    Comme je viens du Java et du C# je suis un peu perdu avec Javascript et la POO prototypal.
    Effectivement je dois approfondir tout cela.
    MCTS Microsoft.
    La conception : Prendre le temps pour gagner du temps.

  5. #5
    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
    Oui, pas facile de sortir du modèle de POO par classes quand on vient du monde Java. D'ailleurs, l'opérateur new a été ajouté à JavaScript pour essayer de rendre les choses plus claires pour les développeurs Java, mais ça n'a fait que rendre les choses encore plus confusantes.
    One Web to rule them all

  6. #6
    Membre confirmé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Points : 637
    Points
    637
    Par défaut
    Donc dans quel cas utilise t on l'un ou l'autre concept ?
    MCTS Microsoft.
    La conception : Prendre le temps pour gagner du temps.

  7. #7
    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
    En général, un constructeur n'a d'utilité que si l'on est susceptible d'en utiliser plusieurs instances.
    Donc, quand tu veux créer plusieurs instances :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function Person(name){        
        this.name = name;
    }
     
    Person.prototype.getName = function() {
      return this.name;
     };

    La propriété prototype de l'objet Function permet de partager les méthodes entre plusieurs instances.

    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
    var personne1 = new Person('toto');
    var personne2 = new Person('titi');
     
    personne1.getName();  // toto 
    personne2.getName(); // titi
     
    // tu peux ajouter à la volée des méthodes au <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block"><span style="color: #0000ff;">prototype</span></span> de <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block">Person</span> pour que toutes les instances en bénéficient :
     
    Person.prototype.ditBonjour = function() {
      return "Salut de la part de " + this.name;
     };
     
    personne1.ditBonjour();  // Salut de la part de toto
    personne2.ditBonjour(); // Salut de la part de titi

    On appelle ça le pattern constructor. Voici un post, et un autre, qui pourrait t'aider à mieux comprendre je pense.
    Il faut faire attention avec new. Cf post récent de Sylvain

    L'autre cas se passe si tu n'as qu'une et une seule instance, un singleton en somme (la gestion d'une base, gestion des logs, etc).

  8. #8
    Membre confirmé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Points : 637
    Points
    637
    Par défaut
    Si j'utilise l'object literal je peux egalement me servir de Object.Create afin de faire de l'objet non ?
    MCTS Microsoft.
    La conception : Prendre le temps pour gagner du temps.

  9. #9
    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
    La déclaration littérale d'un objet revient à le faire hériter du prototype Object.prototype. Autrement dit, ces déclarations sont équivalentes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var a = {};
    var b = Object.create(Object.prototype);
    On peut mélanger les deux, cela reviendra à créer un objet dont le prototype est un autre objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var proto = { bip: function(){ alert('bip'); } };
    var o = Object.create(proto);
    o.bip();
    One Web to rule them all

  10. #10
    Membre du Club
    Homme Profil pro
    aucun
    Inscrit en
    Mars 2014
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Mars 2014
    Messages : 55
    Points : 42
    Points
    42
    Par défaut
    SylvainPV je voudrais savoir si ce code la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var proto = { bip: function(){ alert('bip'); } };
    var o = Object.create(proto);
    o.bip();
    Et equivalent a celui ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var proto = { bip: function(){ alert('bip'); } };
    var Constructeur = function (){};
    Constructeur.prototype = proto;
    var o = new Constructeur();
    o.bip();

  11. #11
    Membre confirmé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Points : 637
    Points
    637
    Par défaut
    Donc nous pouvons faire de la POO avec les 2 facons. D'ou ma premiere question. Car je ne vois vraiment pas quand il faut utiliser l'une ou l'autre facon
    MCTS Microsoft.
    La conception : Prendre le temps pour gagner du temps.

  12. #12
    Membre du Club
    Homme Profil pro
    aucun
    Inscrit en
    Mars 2014
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Mars 2014
    Messages : 55
    Points : 42
    Points
    42
    Par défaut
    Je ne suis pas devellopeur professionel mais je pense que tu peut utiliser les 2 façons sa dépend si tu te fie ou pas de la compatibilité des navigateurs.
    Par exemple Object.create() et disponible seulement à partir de IE9 si tu vise les versions précedentes il te faudra soit utiliser un polyfill ou utiliser la 2 eme méthodes.

    Mais je préfère entendre la solution des pros pour en etre plus certaint.

  13. #13
    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
    Il y a plus de deux façons de faire de la POO en JavaScript, il y a beaucoup de frameworks qui apportent leur propre paradigme, leur vision personnelle de comment on devrait faire les choses.

    Pour répondre à vos questions, topolino et unoomad, au sujet des différences entre new et Object.create, j'ai fait tout un topic dessus pour l'expliquer. Il a déjà été posté en lien ici, je le remets: http://www.developpez.net/forums/d14...aise-pratique/

    Cet aspect hybride ou multi-paradigme de JavaScript est à la fois une force, car il apporte flexibilité et richesse au langage, et un défaut car il est plus compliqué à appréhender et on risque un manque d'homogénéité dans le code entre plusieurs développeurs.
    One Web to rule them all

  14. #14
    Membre du Club
    Homme Profil pro
    aucun
    Inscrit en
    Mars 2014
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Mars 2014
    Messages : 55
    Points : 42
    Points
    42
    Par défaut
    Merci SylvainPV pour ton lien mais j'ai vu ça dans ton post :
    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
    /* le prototype de base de tout objet est Object.prototype
       le prototype Car est un objet, on le crée via Object.create et on lui donne les propriétés qu'auront toutes les voitures */
    var Car = Object.create(Object.prototype);
    Car.wheels = 4;
    Car.drive = function(){
       this.speed = 120;
    };
     
    // on crée une voiture à partir du prototype Car
    var golf = Object.create(Car);
    golf.constructor = "Volkswagen";
    golf.model = "Golf";
     
    Object.getPrototypeOf(golf) === Car; // true ! ENFIN
     
    golf instanceof Car // TypeError: Expecting a function in instanceof check, but got #<Object> ; l'opérateur instanceof est à jeter avec new
    Mais c'est equivalent a ceci aussi non ? :

    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
    var Car = {}  // Tout objet herite de Object.prototype
    Car.wheels = 4;
    Car.drive = function(){
       this.speed = 120;
    };
     
    // On crée ensuite le constructeur de golf
    function golf (){
    this.constructor = "Volkswagen";
    this.model = "Golf";
    }
     
    golf.prototype = Car;
     
    // Enfin on instancie l'objet
    var golf01 = new golf();
     
    Object.getPrototypeOf(golf01) === Car; // true !
     
    golf01 instanceof Car // TypeError: Expecting a function in instanceof check, but got #<Object>
    J'aimerai vos avis ...

  15. #15
    Membre confirmé

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

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Points : 545
    Points
    545
    Par défaut Ne pas oublier le prototypage dynamique !
    Salut,

    Je souhaite porter à votre connaissance une autre possibilité en JavaScript, rarement mis en avant, car peut-être est-elle jugée comme une mauvaise pratique, j’affection tous particulièrement les mauvaise pratiques de ce langage

    Cette possibilité est de pouvoir modifier dynamiquement le prototype d’un object déjà instancié au run-time, cela est pratique lorsque tes données proviennent d'une ressource externe, par exemples un fichier JSON,
    ces données, après évaluation du fichier, sont déjà instanciés en tant que simple Object, Array, RegEx ou String, c’est tout de même bien pratique de pouvoir leur leurs assigner un prototype perso sans avoir à ré-instancier le tous !

    Exemple :
    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
    /****************************************************************
     * @prototype : Vector2D
     *****************************************************************/
    var Vector2D = {
    	/****              Methodes d'instance                   ****/
    	scale : function(s) {
    		this.x *= (s instanceof Object && s.x!==undefined)? s.x : s;
    		this.y *= (s instanceof Object && s.y!==undefined)? s.y : s;
    		return this;
    	},
    	square : function( ) { return this.x*this.x + this.y*this.y; },
    	length : function() { return Math.sqrt(this.square()); },
    	setLength : function(l) 
    	{ 
    		this.scale(l/this.length());
    		return this;
    	},
    	normalize : function()
    	{
    		var l = this.Length();
    		if (l != 0.0)
    			this.scale(1.0 / l)
    		return this;
    	},
    	translate : function(t)
    	{
    		this.x += t.x;
    		this.y += t.y;
    		return this;
    	},
     
    	/****              Methodes statiques                   ****/
    	Add : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    			v.translate(arguments[i]);
    		return v;
    	},
    	Sub : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    		{	
    			arguments[i].__proto__ = Vector2D;
    			v.translate(arguments[i].scale(-1));
    		}
    		return v;
    	}
     
    }
     
    var VertexBuffer = [
    	{ x : 12.65, y : -6.245 },
    	{ x : -3.2565, y : 65.78 },
    	{ x : 89.2565, y : 53.41}
    ];
     
    VertexBuffer.forEach(function(vertice)
    {
    	vertice.__proto__ = Vector2D;
    })
     
    console.log(VertexBuffer[0].length());
    console.log(Vector2D.Add.apply(null, VertexBuffer));
    console.log(Vector2D.Sub.apply(null, VertexBuffer));
    ShaderElement : Bénéficier de l’accélération graphique simplement par une nouvelle balise HTML <shader>
    ODE.js : portage JavaScript du célèbre moteur physique 3D Open Dynamics Engine

  16. #16
    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
    Oui pegase ça se fait, mais ça ne présente pas d'avantage en termes de performance, au contraire. Aussi, __proto__ n'a jamais été un standard.

    https://developer.mozilla.org/fr/doc...setPrototypeOf
    Changer le [[Prototype]] d'un objet, via cette méthode ou via Object.prototype.__proto__ qui est obsolète, est fortement déconseillé. En effet, avec les implémentations modernes de JavaScript, cela est très lent et ralentirait l'exécution du code qui suivrait.
    One Web to rule them all

  17. #17
    Membre confirmé

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

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Points : 545
    Points
    545
    Par défaut
    Oula ! Je n’aurais pas imaginé que cela puisse être lent, même avec le mécanisme des hidden classes (un cast dynamique en c++ ne coûte rien)!

    Du coup va falloir que je benchmark tout ça ! Car au vue de ma volumétrie je ne peux pas me permettre d’utiliser un pattern constructeur par duplication ou par wrapper, et encore moins, de réécrire un parseur de fichier JSON, en javascript, qui instancierait directement mes objets avec le bon proto.

    Le plus performant est, certainement, de pas lier mes objets à mon proto, ce qui me forcera à écrire ce genre de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vector2D.translate.call(Vector2D.normalize.call(v1),{ x : 10, y :-2})
    a la place de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v1.normalize().translate({ x : 10, y :-2});
    Arf non ! C’est vraiment trop laid !
    ShaderElement : Bénéficier de l’accélération graphique simplement par une nouvelle balise HTML <shader>
    ODE.js : portage JavaScript du célèbre moteur physique 3D Open Dynamics Engine

  18. #18
    Membre confirmé

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

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Points : 545
    Points
    545
    Par défaut
    Bonjour

    J’ai benchmarké la mécanique de changement de prototype pour la comparer à une nouvelle instanciation avec un constructeur par copie … et le résultat est clairement en faveur du changement de proto !

    J’ai exécuté le script suivant :
    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
    /****************************************************************
     * @prototype : Vector2D
     *****************************************************************/
    var Vector2D = {
    	/****              Methodes d'instance                   ****/
    	scale : function(s) {
    		this.x *= (s instanceof Object && s.x!==undefined)? s.x : s;
    		this.y *= (s instanceof Object && s.y!==undefined)? s.y : s;
    		return this;
    	},
    	square : function( ) { return this.x*this.x + this.y*this.y; },
    	length : function() { return Math.sqrt(this.square()); },
    	setLength : function(l) 
    	{ 
    		this.scale(l/this.length());
    		return this;
    	},
    	normalize : function()
    	{
    		var l = this.length();
    		if (l != 0.0)
    			this.scale(1.0 / l)
    		return this;
    	},
    	translate : function(t)
    	{
    		this.x += t.x;
    		this.y += t.y;
    		return this;
    	},
     
    	/****              Methodes statiques                   ****/
    	Add : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    			v.translate(arguments[i]);
    		return v;
    	},
    	Sub : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    		{	
    			arguments[i].__proto__ = Vector2D;
    			v.translate(arguments[i].scale(-1));
    		}
    		return v;
    	}
     
    }
     
    function Vector2Dconstructor(x,y) { this.x = x; this.y = y }
    Vector2Dconstructor.prototype =  Vector2D;
     
    var vertexCount = 500000;
    var VertexBuffer = new Array(vertexCount);
    for(var i=0;i<vertexCount;i++)
    {
    	VertexBuffer[i] ={ x : Math.random() *1000, y : Math.random() *1000 };
    }
     
    console.time('setProto');
    VertexBuffer.forEach(function(vertice)
    {
    	vertice.__proto__ = Vector2D;
    })
    console.timeEnd('setProto');
     
    var Vectors = new Array(vertexCount),v=0;
    console.time('constructor');
    VertexBuffer.forEach(function(v)
    {
    	Vectors[v++] = new Vector2Dconstructor(v.x,v.y);
    })
    console.timeEnd('constructor');
    Sur Firefox V32 :
    setProto: 2112ms
    constructor: 4746ms
    Sur Chrome V38 :
    setProto: 584.000ms
    constructor: 1641.000ms
    Sur NodeJS V0.10.29 :
    setProto: 109ms
    constructor: 921ms
    Edit : J’ai modifié mon script pour comparer les 3 méthodes d’instanciation d’objet : l’operateur new, Obejct.create et litteral + __proto__
    avec ce srcipt :
    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
    /****************************************************************
     * @prototype : Vector2D
     *****************************************************************/
    var Vector2D = {
    	/****              Methodes d'instance                   ****/
    	scale : function(s) {
    		this.x *= (s instanceof Object && s.x!==undefined)? s.x : s;
    		this.y *= (s instanceof Object && s.y!==undefined)? s.y : s;
    		return this;
    	},
    	square : function( ) { return this.x*this.x + this.y*this.y; },
    	length : function() { return Math.sqrt(this.square()); },
    	setLength : function(l) 
    	{ 
    		this.scale(l/this.length());
    		return this;
    	},
    	normalize : function()
    	{
    		var l = this.length();
    		if (l != 0.0)
    			this.scale(1.0 / l)
    		return this;
    	},
    	translate : function(t)
    	{
    		this.x += t.x;
    		this.y += t.y;
    		return this;
    	},
     
    	/****              Methodes statiques                   ****/
    	Add : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    			v.translate(arguments[i]);
    		return v;
    	},
    	Sub : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    		{	
    			arguments[i].__proto__ = Vector2D;
    			v.translate(arguments[i].scale(-1));
    		}
    		return v;
    	}
     
    }
     
    function Vector2Dconstructor(x,y) { this.x = x; this.y = y }
    Vector2Dconstructor.prototype =  Vector2D;
     
    var vertexCount = 500000;
    console.time('setProto');
    for(var i=0;i<vertexCount;i++)
    {
    	var v = { x : Math.random() *1000, y : Math.random() *1000 };
    	v.__proto__ = Vector2D
    }
    console.timeEnd('setProto');
     
    console.time('constructor');
    for(var i=0;i<vertexCount;i++)
    {
    	var v = new Vector2Dconstructor( Math.random() *1000,Math.random() *1000);
    }
    console.timeEnd('constructor');
     
    console.time('Object.create');
    for(var i=0;i<vertexCount;i++)
    {
    	var v = Object.create(Vector2D, { x : { value : Math.random() *1000}, y : { value : Math.random() *1000}});
    }
    console.timeEnd('Object.create');
    Sur Firefox V32 :
    setProto: 1750ms
    constructor: 2062ms
    Object.create: 3195ms
    Sur Chrome V38 :
    setProto: 1822.000ms
    constructor: 1293.000ms
    Object.create: 5259.000ms
    Sur NodeJS V0.10.29 :
    setProto: 212ms
    constructor: 13ms
    Object.create: 1574ms
    ShaderElement : Bénéficier de l’accélération graphique simplement par une nouvelle balise HTML <shader>
    ODE.js : portage JavaScript du célèbre moteur physique 3D Open Dynamics Engine

  19. #19
    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
    Mes résultats :

    Chrome 38
    setProto: 289.239ms
    constructor: 39.857ms
    Object.create: 1746.948ms

    Firefox 31
    setProto : 361.53ms
    constructor : 57.99ms
    Object.create : 750.69ms


    new est donc particulièrement optimisé par les moteurs JS

    Sinon dans ton premier script, il faut compter aussi l'instanciation des objets dans le timer en plus du changement de proto, tu triches un peu là
    One Web to rule them all

  20. #20
    Membre confirmé

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

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Points : 545
    Points
    545
    Par défaut
    Citation Envoyé par SylvainPV Voir le message
    Sinon dans ton premier script, il faut compter aussi l'instanciation des objets dans le timer en plus du changement de proto, tu triches un peu là
    Je ne triche pas ! Mon problème initial est : Quel est la méthode la plus performant pour prototyper des objets déjà instanciés (par eval ou par JSON.parse) ?

    Il n’y a pas 36 solutions :
    • Soit je change dynamiquement le proto
    • Soit je ré-instancie un nouveau objet avec un constructeur par copie
    • Soit je ne lie pas l’objet au prototype


    Nouveau script pour comparer l’exécution de méthode avec un objet lié a un protype, ou pas :
    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
    /****************************************************************
     * @prototype : Vector2D
     *****************************************************************/
    var Vector2D = {
    	/****              Methodes d'instance                   ****/
    	scale : function(s) {
    		this.x *= (s instanceof Object && s.x!==undefined)? s.x : s;
    		this.y *= (s instanceof Object && s.y!==undefined)? s.y : s;
    		return this;
    	},
    	square : function( ) { return this.x*this.x + this.y*this.y; },
    	length : function() { return Math.sqrt(this.square()); },
    	setLength : function(l) 
    	{ 
    		this.scale(l/this.length());
    		return this;
    	},
    	normalize : function()
    	{
    		var l = this.length();
    		if (l != 0.0)
    			this.scale(1.0 / l)
    		return this;
    	},
    	translate : function(t)
    	{
    		this.x += t.x;
    		this.y += t.y;
    		return this;
    	},
     
    	/****              Methodes statiques                   ****/
    	Add : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    			v.translate(arguments[i]);
    		return v;
    	},
    	Sub : function ()
    	{
    		var v = { x : arguments[0].x, y : arguments[0].y };
    		v.__proto__ = Vector2D;
    		for(var i=1;i<arguments.length;i++)
    		{	
    			arguments[i].__proto__ = Vector2D;
    			v.translate(arguments[i].scale(-1));
    		}
    		return v;
    	}
     
    }
     
    var vertexCount = 500000;
    var VertexBuffer = new Array(vertexCount);
    for(var i=0;i<vertexCount;i++)
    {
    	VertexBuffer[i] ={ x : Math.random() *1000, y : Math.random() *1000 };
    }
     
    console.time('setProto');
    VertexBuffer.forEach(function(v)
    {
    	v.__proto__ = Vector2D;
    	v.normalize().translate({ x : 10, y :-2});
    })
    console.timeEnd('setProto');
     
    console.time('no Proto');
    VertexBuffer.forEach(function(v)
    {
    	Vector2D.translate.call(Vector2D.normalize.call(v),{ x : 10, y :-2})
    })
    console.timeEnd('no Proto');
    Mon Firefox s’est mis à jour en V33 et dans cette version console.time n’existe plus

    Sur Chrome V38 :
    setProto: 1426.000ms
    no Proto: 1654.000ms
    Sur NodeJS V0.10.29 :
    setProto: 327ms
    no Proto: 224ms
    Bon j'en conclus que je ne vais pas me gêner à utiliser le prototypage dynamique !
    ShaderElement : Bénéficier de l’accélération graphique simplement par une nouvelle balise HTML <shader>
    ODE.js : portage JavaScript du célèbre moteur physique 3D Open Dynamics Engine

Discussions similaires

  1. Réponses: 0
    Dernier message: 02/06/2014, 20h20
  2. objet literal et objet avec constructeur
    Par hellalaboy dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 27/07/2011, 14h31
  3. Bug ie7 . Objet javascript et prototype
    Par Sourrisseau dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 23/04/2009, 14h19
  4. [Prototype] Etendre l'objet Date
    Par mp59100 dans le forum Bibliothèques & Frameworks
    Réponses: 3
    Dernier message: 24/02/2009, 08h54
  5. [Prototype] Une couche d'abstraction de l'objet XMLHTTPRequest
    Par Tanhys dans le forum Bibliothèques & Frameworks
    Réponses: 3
    Dernier message: 31/03/2007, 15h12

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