11484 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous
Comme je suis en train de développer une application administrative un peu complexe, je suis très orienté JavaScript ces temps ci.
Et comme je ne sais plus programmer autrement qu'en utilisant des objets, j'ai en permanence à écrire des instructions telles que

document.getElementById('bidule').addEventListener('click', this.maFonction.bind(this));

Il y a une chose qui me pose une question:
Pour moi, si on affecte une méthode d'un objet à un évènement, c'est TOUJOURS pour que la méthode s'applique dans le contexte de l'objet. Je ne vois pas très bien dans quels cas on pourrait avoir besoin d'écrire

document.getElementById('bidule').addEventListener('click', this.maFonction);

Mais peut être que c'est utile dans certains cas???

Votre avis m'intéresse.
Modérateur
PapyJP a écrit :
Pour moi, si on affecte une méthode d'un objet à un évènement, c'est TOUJOURS pour que la méthode s'applique dans le contexte de l'objet


Bonjour,

Je ne comprends pas vraiment tes propos. Ils sont confus. Peux tu donner un exemple un peu plus explicite ?
Je vais essayer d'expliquer autrement:
J'ai un objet défini par

function MonObjet(...) {
    this.truc = 1234;
    this.machin = 5678;
    ..........
    this.maFonction = function(...) {
        this.truc = "abcd";
        this.machin = "efgh";
    }
    var bidule = document.getElementById('bidule');
    bidule.addEventListener('click', this.maFonction.bind(this);
    ............
}

Explication: quand on clique sur l'élément "bidule", on veut lancer la fonction interne à l'objet qui s'appelle "maFonction". En d'autres termes on veut changer la valeur des propriétés "truc" et "machin" de l'objet quand on clique sur cet élément: on veut donc que le "this.truc" utilisé dans la fonction soit la même variable que celle qui a été initialisée à 1234 lors de la définition de l'objet.

Si on écrit
bidule.addEventListener('click', this.maFonction);

lors de l'exécution, la fonction ne prendra pas la même variable "this.truc", elle prendra (et éventuellement créera) une variable au niveau window, c'est à dire pour faire court une variable globale, et pas la propriété de l'objet.
Ma question c'est : est-ce que vous connaissez des cas où il serait utile d'utiliser une telle syntaxe, et pour quoi faire?
J'espère que c'est plus clair.
Modifié par PapyJP (20 Sep 2017 - 19:38)
Modérateur
Je t'avoue que ton explication est encore confuse.

Bref, une chose à savoir en poo : l'objet doit être le plus cohérent possible et il est préférable que les dépendances ne doivent pas être forte (un aspect délicat à mettre en place).

Ton écriture est ancienne et je t'avoue que je n'écris plus comme ça depuis belle lurette. Ceci dit, dans un objet on peut très bien appeler une méthode. Cette méthode peut être private ou protected en générale. Bien qu'il n'y ait pas ces mots clefs (sauf ce qu'apporte microsoft avec son typescript qui est très prometteur mais pas encore standardisé malheureusement), tu peux cependant avec ton type de syntaxe simuler ça.
Modérateur
a écrit :

Ma question c'est : est-ce que vous connaissez des cas où il serait utile d'utiliser une telle syntaxe, et pour quoi faire?

Lorsque la méthode est «statique», autrement dit qu'elle n'utilise pas le mot-clé this.

Ou lorsque this.maFonction est défini de manière externe. Un cas courant serait les callbacks:


this.registerCallback(callback){
  this.callback = callback;
}
…
this.faitUnTruc(){
  …
  bidule.addEventListener('click', this.callback);
}
Oui, je comprends bien qu’on peut faire des choses de ce genre, mais ça sert à quoi par rapport à une fonction externe à l’objet ?
Modérateur
PapyJP a écrit :
Oui, je comprends bien qu’on peut faire des choses de ce genre, mais ça sert à quoi par rapport à une fonction externe à l’objet ?


niuxe a écrit :

...
l'objet doit être le plus cohérent possible
....

Modifié par niuxe (21 Sep 2017 - 21:33)
niuxe a écrit :

Bref, une chose à savoir en poo : l'objet doit être le plus cohérent possible et il est préférable que les dépendances ne doivent pas être forte (un aspect délicat à mettre en place).

??? c'est justement parce que je veux que ce soit cohérent que j'écris les choses comme ça.
Si je veux que le traitement de l'évènement concerne mon objet, il est naturel que la méthode appartienne à l'objet. Si je ne veux pas que le traitement de l'évènement concerne l'objet, je ne vois pas pourquoi la méthode serait dans l'objet. C'est aussi bête que ça.

Dans mon esprit, quand on est dans le corps d'un objet, toute référence à une méthode de l'objet devrait implicitement signifier que c'est le contexte de l'objet qui est le contexte de la méthode, je veux dire que quand on utilise this dans une méthode d'un objet, il est naturel que cela concerne les propriétés de l'objet.
C'est comme ça que ça fonctionne en PHP, je ne vois pas pourquoi il n'en est pas de même avec JS.
Ma compréhension, en tant que vieux c... ayant fait partie des gens qui ont introduit la POO dans le monde du logiciel professionnel je veux dire en dehors des centres de recherche dans les années 1980, c'est que ça aurait dû être comme ça en JS aussi, et que le .bind(this) est un patch pour corriger une déficience du langage sans devoir remette en cause les millions de lignes de code JS écrits autrement.

niuxe a écrit :
Ton écriture est ancienne et je t'avoue que je n'écris plus comme ça depuis belle lurette.

Comment écris tu ce genre de choses? Je n'arrive même pas à imaginer comment on peut faire, ça m'intéresse.
niuxe a écrit :
Ceci dit, dans un objet on peut très bien appeler une méthode.

Je dirais même plus: un objet comporte des propriétés et de méthodes. Un objet sans méthode, c'est un bloc de données qu'on va utiliser de l'extérieur, ce n'est plus de la POO.

niuxe a écrit :
Cette méthode peut être private ou protected en général. Bien qu'il n'y ait pas ces mots clefs (sauf ce qu'apporte microsoft avec son typescript qui est très prometteur mais pas encore standardisé malheureusement), tu peux cependant avec ton type de syntaxe simuler ça.

Bien entendu, il n'y a rien à "simuler", simplement veiller à ne pas appeler de l'extérieur de l'objet des méthodes qui sont pensées pour être privées ou accéder les propriétés de l'objet qui sont sensées être privées. Dans l'état actuel du langage, c'est simplement une discipline de codage.
Les mots clés en question, le jour où ils existeront dans tous les navigateurs du marché, permettront de déclarer qu'une méthode ou une propriété peut ou non être utilisée de l'extérieur de l'objet. Ce sera certainement un plus pour éviter des utilisations intempestives, mais il y a peu de chances que je sois encore de ce monde pour voir ça...
Modifié par PapyJP (22 Sep 2017 - 10:44)
Modérateur
PapyJP a écrit :
Oui, je comprends bien qu’on peut faire des choses de ce genre, mais ça sert à quoi par rapport à une fonction externe à l’objet ?


C'est juste une question d'organisation, mais ça n'a pas d'intérêt particulier, hormis de limiter le nombre de fonction esseulées dans le namespace global. Organisation, relecture du code, maintenance et tout ça lorsque l'on commence à avoir quelques milliers de lignes de code.
Meilleure solution
kustolovic a écrit :


C'est juste une question d'organisation, mais ça n'a pas d'intérêt particulier, hormis de limiter le nombre de fonction esseulées dans le namespace global. Organisation, relecture du code, maintenance et tout ça lorsque l'on commence à avoir quelques milliers de lignes de code.

Merci de ta réponse
C'était mon sentiment également, je me demandais si je n'étais pas passé à côté d'un truc utile sans le voir.
Modérateur
PapyJP a écrit :

C'est comme ça que ça fonctionne en PHP, je ne vois pas pourquoi il n'en est pas de même avec JS.


Parce qu'à la base , Javascript n'a jamais été un langage Objet. C'était un langage orienté prototype..... D'où l’ambiguïté avec this Smiley cligne

Je me souviens maintes fois avoir écrit :

var _this = this;
var _that = this; // et autres variantes


Désormais, on peut oublier puisque la syntaxe s'est améliorée....

PapyJP a écrit :

Comment écris tu ce genre de choses? Je n'arrive même pas à imaginer comment on peut faire, ça m'intéresse.


Support d'ECMAScript 6


PapyJP a écrit :

Je dirais même plus: un objet comporte des propriétés et de méthodes. Un objet sans méthode, c'est un bloc de données qu'on va utiliser de l'extérieur, ce n'est plus de la POO.


objet statique ?

Smiley cligne
Modifié par niuxe (22 Sep 2017 - 11:57)
Merci pour ces éclaircissements
Il est vrai que le concept de prototype n’est pas la même chose que le concept de classes d’objets et que tout ce bazar vient de là.
———————
ECMAScript6? Est-ce qu’on peut vraiment s’y fier? Est-ce assez stable et assez généralement supporté pour qu’on puisse faire des développements avec? J’ai envie d’essayer
———————
Oui, bien sûr, un objet statique est un objet sans méthodes, mais je n’y pense jamais comme étant de « vrais » objets...
Modérateur
PapyJP a écrit :

Oui, bien sûr, un objet statique est un objet sans méthodes, mais je n’y pense jamais comme étant de « vrais » objets...


Attention, un objet static peut avoir des méthodes. Dans ce cas là on parlera de méthode de la classe en elle même et non d'une instance.
Administrateur
PapyJP a écrit :
ECMAScript6? Est-ce qu’on peut vraiment s’y fier? Est-ce assez stable et assez généralement supporté pour qu’on puisse faire des développements avec?

J'ai envie de troller et de répondre que globalement c'est moins bien supporté que Flexbox et Grid Layout : https://kangax.github.io/compat-table/es6/

Plus concrètement : aujourd'hui si tu veux que ça fonctionne sous IE10 voire IE11, il te faut des librairies alternatives (polyfill).
Modérateur
Raphael a écrit :

J'ai envie de troller et de répondre que globalement c'est moins bien supporté que Flexbox et Grid Layout : https://kangax.github.io/compat-table/es6/

Plus concrètement : aujourd'hui si tu veux que ça fonctionne sous IE10 voire IE11, il te faut des librairies alternatives (polyfill).


Erf, on est vendredÿ ou trolldi Smiley smile

Babel avec les packages qui vont bien Smiley smile . Browserify ou webpack seront utiles (largement supérieur à Requirejs). Tout dépend de l'architecture de dev que l'on compte mettre en place.

On ne peut pas tout faire (d'où les quelques polyfills => mais il me semble que ce ne soit pas suffisant pour certains cas). La syntaxe générale est assez bien supportée. Je viens de terminer une librairie en ES6. Franchement, je m'en suis bien sorti.
Modifié par niuxe (22 Sep 2017 - 14:26)