82 votes

L'utilisation de fonctions anonymes affecte-t-elle les performances ?

Je me suis demandé s'il y avait une différence de performance entre l'utilisation de fonctions nommées et de fonctions anonymes en Javascript ?

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something
    };
}

vs

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

La première est plus ordonnée puisqu'elle n'encombre pas votre code de fonctions rarement utilisées, mais est-ce important que vous déclariez cette fonction plusieurs fois ?

83voto

Atif Aziz Points 16967

Le problème de performance ici est le coût de la création d'un nouvel objet fonction à chaque itération de la boucle et non le fait que vous utilisez une fonction anonyme :

for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

Vous créez un millier d'objets fonctionnels distincts même s'ils ont le même corps de code et aucune liaison avec la portée lexicale ( fermeture ). En revanche, la méthode suivante semble plus rapide, car elle affecte simplement l'élément même aux éléments du tableau tout au long de la boucle :

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

Si vous créez la fonction anonyme avant d'entrer dans la boucle, puis que vous n'affectez les références à cette fonction qu'aux éléments du tableau à l'intérieur de la boucle, vous constaterez qu'il n'y a aucune différence de performance ou de sémantique par rapport à la version de la fonction nommée :

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = handler;
}

En bref, l'utilisation de fonctions anonymes plutôt que de fonctions nommées n'entraîne aucun coût de performance observable.

Soit dit en passant, il peut sembler, d'après ce qui précède, qu'il n'y a aucune différence entre :

function myEventHandler() { /* ... */ }

et :

var myEventHandler = function() { /* ... */ }

Le premier est un déclaration de fonction alors que le dernier est une affectation de variable à une fonction anonyme. Bien qu'ils puissent sembler avoir le même effet, JavaScript les traite de manière légèrement différente. Pour comprendre la différence, je vous recommande la lecture de " Ambiguïté des déclarations de fonctions JavaScript ".

21voto

nickf Points 185423

Voici mon code de test :

var dummyVar;
function test1() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = myFunc;
    }
}

function test2() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = function() {
            var x = 0;
            x++;
        };
    }
}

function myFunc() {
    var x = 0;
    x++;
}

document.onclick = function() {
    var start = new Date();
    test1();
    var mid = new Date();
    test2();
    var end = new Date();
    alert ("Test 1: " + (mid - start) + "\n Test 2: " + (end - mid));
}

Les résultats :
Test 1 : 142ms Test 2 : 1983ms

Il semble que le moteur JS ne reconnaisse pas que c'est la même fonction dans Test2 et la compile à chaque fois.

3voto

Arthur Thomas Points 3399

J'ai trouvé cela intéressant : http://weblog.raganwald.com/2007/08/ruminations-about-performance-of.html

Je pense que cela dépend du navigateur.

2voto

Tom Leys Points 10453

En tant que principe général de conception, vous devriez éviter d'implémenter le même code plusieurs fois. Au lieu de cela, vous devez extraire le code commun dans une fonction et exécuter cette fonction (générale, bien testée, facile à modifier) à partir de plusieurs endroits.

Si (contrairement à ce que vous déduisez de votre question) vous déclarez la fonction interne une fois et utilisez ce code une fois (et n'avez rien d'autre d'identique dans votre programme) alors une fonction autonome probablement (c'est une supposition) est traitée de la même manière par le compilateur qu'une fonction nommée normale.

C'est une fonction très utile dans des cas spécifiques, mais elle ne devrait pas être utilisée dans de nombreuses situations.

1voto

pcorcoran Points 2350

Les objets anonymes sont plus rapides que les objets nommés. Mais l'appel d'un plus grand nombre de fonctions est plus coûteux, et ce dans une mesure qui éclipse les économies que vous pourriez réaliser en utilisant des fonctions anonymes. Chaque fonction appelée s'ajoute à la pile d'appel, ce qui introduit une quantité faible mais non négligeable de surcharge.

Mais à moins que vous n'écriviez des routines de cryptage/décryptage ou quelque chose d'aussi sensible aux performances, comme beaucoup d'autres l'ont noté, il est toujours préférable d'optimiser un code élégant et facile à lire plutôt qu'un code rapide.

En supposant que vous écrivez un code bien architecturé, les questions de vitesse devraient être de la responsabilité de ceux qui écrivent les interprètes/compilateurs.

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