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 :

Prototypes et Itérations


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut Prototypes et Itérations
    Bonjour à tous.

    Quelqu'un saurait-il m'expliquer pourquoi l'ajout de méthodes à un objet rends cette méthode visible lors de l'itération for ?

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Array.prototype.min = function () {
    	var min;
    	for (i in this) {
    		write(this[i]);
    		if (min == undefined || min > this[i])
    			min = this[i];
    	}
    	return min;
    }
     
    write([1,2,3].min());
    Le problème c'est que j'ai besoin d'ajouter des fonctionnalités à des objets natifs mais cela à tendance à perturber jQuery (surtout quand on ajoute des méthodes à Object, c'est la cata).

  2. #2
    Membre expérimenté
    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
    Par défaut
    Cela est du au mécanisme d'héritage en javascript. Lorqu'une propriété ne peut être résolue le runtime va chercher de manière récursive dans la chaine de prototypage.

    De la même manière lors d'une itération sur les clés tu itère sur les clés de l'objet (instances) mais aussi sur les clés visibles dans ta chaine de prototypage.

    Pour itérer sur un objet sans itérer les clés héritées il faut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(var i on obj) if (obj.hasOwnProperty(i)){
        // loop
    }
    De plus tu ne dois pas itérer un tableau par clés, mais par indexs, sinon tu traversera aussi des propriétés de l'instance comme length (ce que tu ne veux pas faire) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(var i = 0, n = arr.length; i<n; i++){
        // loop
    }
    PS : il est considéré comme une mauvaise pratique d'augmenter les objets natifs. Il y a toujours une meilleure solution que d'ouvrir cette boîte de Pandore.

  3. #3
    Membre Expert 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 : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Effectivement, c'est dangereux d'ajouter des prototypes à tous les Objets et jQuery a parfois un peu du mal avec ça.

    essaye de faire des trucs du genre :

    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
     
    // nouvelle classe MyObject avec héritage(extend) basique
    function MyObject(h) {
        if (h) this.extend(h);
        return this;
    }
    MyObject.prototype.extend = function (o) {
        for (var i in o)
            this[i] = o[i];
        return this;
    };
     
    // déclaration de prototypes personalisés
    MyObject.prototype.toArray = function () {
        var r = [];
        for (var i in this)
            if (typeof (this[i]) != 'function' && typeof (this[i]) != 'object') r.push(this[i]);
        return r;
    }
     
    // création d'un nouvel objet "myObject" à partir d'un objet et utilisation de méthode prototypée
    var obj = new MyObject({
        name: 'john',
        age: 22
    });
    alert(obj.toArray());
     
     
    //--------------------------------------------------------
    // après tu peux facilement faire des nouvelles classes à partir de myObject :
    //--------------------------------------------------------
     
    // nouvelle classe personalisée
    function human(h) {
        return (new MyObject(h)).extend(this);
    }
    human.prototype.sing = function () {
        alert('lalala');
    };
     
    // utilisation
    var me;
    me = new human({
        eyes: 'blues',
        height: '1m80'
    });
    me = me.extend({
        hair: 'red'
    });
    me.sing();
    alert(me.toArray());
    edit: indentation

  4. #4
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut
    Merci @TheGwy. Ce que je ne comprenais pas c'est pourquoi les membre natifs des objets ne se retrouvent pas dans la liste des clés. Pourtant cela fait effectivement partie de leur prototype. Dois-je en déduire que c'est la VM qui "masque" ces clés ?

    PS : il est considéré comme une mauvaise pratique d'augmenter les objets natifs. Il y a toujours une meilleure solution que d'ouvrir cette boîte de Pandore.
    C'est noté. En revanche c'est une alternative séduisante pour palier les insuffisances du langage au niveau fonctionnel (c'est vrai quoi, y'a même pas trim sur les chaines )
    Vu qu'on ne devrait pas les augmenter, peut-on au moins en hériter ?

  5. #5
    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 : 54
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    Citation Envoyé par Benjamin Delespierre
    c'est vrai quoi, y'a même pas trim sur les chaines
    Heu... si : Le "core" JavaScript s'enrichit de nouvelles méthodes.
    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

  6. #6
    Membre expérimenté
    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
    Par défaut
    Citation Envoyé par Benjamin Delespierre Voir le message
    Merci @TheGwy. Ce que je ne comprenais pas c'est pourquoi les membre natifs des objets ne se retrouvent pas dans la liste des clés. Pourtant cela fait effectivement partie de leur prototype. Dois-je en déduire que c'est la VM qui "masque" ces clés ?
    Exactement, il y a une propriété interne DontEnum qui n'est pas accessible au code client.
    https://developer.mozilla.org/en/ECM...Enum_attribute
    Les nouvelles API ES5 permettent d'avoir accès à cette propriété, mais d'ici la que ce soit utilisable partout, tu as le temps de venir voir.

    Citation Envoyé par Benjamin Delespierre Voir le message
    C'est noté. En revanche c'est une alternative séduisante pour palier les insuffisances du langage au niveau fonctionnel (c'est vrai quoi, y'a même pas trim sur les chaines )
    Vu qu'on ne devrait pas les augmenter, peut-on au moins en hériter ?
    Oui, comme Willpower l'a montré tu peux parfaitement faire un Objet qui hérite ou encapsule un objet natif, et étendre celui-ci de manière sûre.

    Personnellement je suis plutôt adepte de l'objet avec des fonctions utilitaires statiques (genre StringUtils, etc). C'est un peu plus "lourd" syntaxiquement mais très clair niveau compréhension.

    Après si c'est un projet de petite ampleur où tu es l'auteur de tout le code (pas de passif, source externes, mashups, librairies, plugins) tu peux te permettre d'étendre les objets natifs car tu ne risque pas de casser du code qui n'est pas le tiens. Mais c'est quand même rare de se retrouver dans ce cas.

    Un bon article sur la question avec plusieurs approches décortiquées :
    http://perfectionkills.com/extending...s-evil-or-not/

  7. #7
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut
    Oui, comme Willpower l'a montré tu peux parfaitement faire un Objet qui hérite ou encapsule un objet natif, et étendre celui-ci de manière sûre.
    Encapsuler ça va, mais pour l'héritage je galère comme un veau...

    J'ai tenté ça mais visiblement il manque quelque chose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    myString.prototype = new String;
    myString.prototype.constructor = myString;
     
    function myString ( str ) {
    	String.call(this, str);
    }
     
    var str = new myString('test');
     
    dump(str instanceof String); // true
     
    write(str); // TypeError: String.prototype.valueOf called on incompatible Object

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Prototype] Je ne comprends pas
    Par SpaceFrog dans le forum Bibliothèques & Frameworks
    Réponses: 30
    Dernier message: 15/12/2005, 10h59
  2. Réponses: 6
    Dernier message: 20/11/2005, 02h53
  3. [ JSP ] Itération en JSP
    Par samios dans le forum Servlets/JSP
    Réponses: 7
    Dernier message: 22/10/2005, 18h15
  4. [Système] Récursivité et itération
    Par Floréal dans le forum Langage
    Réponses: 8
    Dernier message: 19/04/2005, 14h57
  5. Récupérer le prototype d'une fonction
    Par uaz dans le forum Général Python
    Réponses: 2
    Dernier message: 27/07/2004, 17h24

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