12 votes

Efficacité de la création d'un gestionnaire d'événements dans une boucle imbriquée : est-ce que je crée 1440 fonctions ici ?

Je viens de développer un petit code pour créer une table 24x60. Je veux imprimer l'identifiant de chaque <td> sur mouseover :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
table {
    background-color:blue;
}
td {
    width: 2px;
    height: 2px;
    background-color:red;
}
</style>
</head>
<body>
<table id="time-table"></table>
<script type="text/javascript">
var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = function ( e ) {
            console.log( this.id );
        }
        row.appendChild( td );
    }
    table.appendChild( row );
}
</script>
</body>
</html>

Le code fonctionne, mais je me demande maintenant s'il est optimisé. Est-ce que je crée 1440 fonctions de gestion d'événements dans les boucles imbriquées ? Ou bien l'interpréteur JavaScript est-il suffisamment intelligent pour ne créer qu'une seule fonction et l'assigner à 1440 <td> éléments ?

12voto

Felix Kling Points 247451

Non, JavaScript n'optimisera rien (peut-être que certaines implémentations le font, mais il ne faut pas s'y fier). Vous créez vraiment beaucoup de fonctions.

Mieux définir la fonction une fois et le réutiliser :

var handler = function() {
    console.log(this.id);
}

for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = handler;
        row.appendChild( td );
    }
    table.appendChild( row );
}

Ou envisager d'utiliser délégation d'événements c'est-à-dire en liant le gestionnaire à un ancêtre des cellules :

table.onmouseover = function(event) {
    event = event || window.event;
    var target = event.target || event.srcElement;

    if(target.nodeName === 'TD') {
        console.log(target.id);
    }
};

Cela fonctionne, car les événements remontent dans l'arbre DOM et peuvent même être plus performants dans certains navigateurs.

Une bonne source d'information sur la gestion des événements est les articles sur quirksmode.org .

1voto

jbabey Points 20696

Une petite modification, par sécurité :

var myFunc = function (e) {
    console.log( this.id );
};

var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = myFunc;
        row.appendChild( td );
    }
    table.appendChild( row );
}

1voto

jfriend00 Points 152127

Je suggérerais de mettre un gestionnaire d'événements sur la table et d'utiliser le bouillonnement d'événements pour le gérer en un seul endroit :

var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        row.appendChild( td );
    }
    table.appendChild( row );
}
table.addEventListener('mouseover', function(e) {
    console.log(e.target.id);
}, false);

Pour les anciennes versions d'IE, vous devez utiliser attachEvent au lieu de addEventListener.

1voto

Tharabas Points 2288

Oui, vous définissez une fonction sans nom pour chaque élément, mais vous pourriez simplement définir la fonction en dehors de la boucle et y faire référence.

var printMyId = function(e) {
  console.log(e.srcElement.id);
};
var table = document.getElementById("time-table");
for (var r = 0; r < 24; r++) {
  var row = document.createElement("tr");
  for (var c = 0; c < 60; c++) {
    var td = document.createElement("td");
    td.id = "td-" + r + "-" + c;
    td.onmouseover = printMyId;
    row.appendChild(td);
  }
  table.appendChild(row);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X