60 votes

Comment contourner l'erreur jslint 'Ne créez pas de fonctions dans une boucle.'

Je suis en train de travailler sur la fabrication de tous nos code JS passer à travers jslint, parfois avec beaucoup de peaufinage avec les options pour obtenir le code hérité passer pour l'instant sur l'intention de le fixer correctement plus tard.

Il y a une chose que jslint se plaint que je n'ai pas le contourner. C'est lors de l'utilisation de constructions de ce genre, nous obtenons l'erreur à Ne pas faire de fonctions à l'intérieur d'une boucle.'

        for (prop in newObject) {
        // Check if we're overwriting an existing function
        if (typeof newObject[prop] === "function" && typeof _super[prop] === "function" &&
        fnTest.test(newObject[prop])) {
            prototype[prop] = (function (name, func) {
                return function () {
                    var result, old_super;

                    old_super = this._super;
                    this._super = _super[name];
                    result = func.apply(this, arguments);
                    this._super = old_super;

                    return result;
                };
            })(prop, newObject[prop]);
        }

Cette boucle fait partie d'un JS de mise en œuvre de la classique héritage où les classes qui étendent les classes existantes de conserver les super-propriété de l'extension de la classe lors de l'appel d'un membre de la classe étendue. Juste pour préciser, la mise en œuvre ci-dessus est inspiré par ce post de blog par John Resig.

Mais nous avons aussi d'autres instances de fonctions créées à l'intérieur d'une boucle.

La seule solution pour l'instant est à exclure ces fichiers JS de jslint, mais nous aimerions utiliser jslint pour le code de validation et de vérification de la syntaxe dans le cadre de notre intégration continue et de workflow de build.

Est-il une meilleure façon de mettre en œuvre des fonctionnalités comme cela ou est-il un moyen de bidouiller le code comme ceci par le biais de jslint?

65voto

Skilldrick Points 33002

Douglas Crockford a créé un nouveau moyen idiomatique de réaliser ce qui précède - son ancienne technique consistait à utiliser une fonction interne pour lier les variables, mais la nouvelle technique utilise un créateur de fonctions. Voir la diapositive 74 dans les diapositives pour son exposé «Function the Ultimate» .

Pour les paresseux, voici le code:

 function make_handler(div_id) {
    return function () {
        alert(div_id);
    };
}
for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = make_handler(div_id);
}
 

12voto

Zhami Points 4851

(Je viens de tombé sur cette questions que plusieurs mois après qu'il a été posté...)

Si vous faites une fonction dans une boucle, une instance d'une fonction est créée pour chaque itération de la boucle. À moins que la fonction qui est fait est fait différente pour chaque itération, puis d'utiliser la méthode de mettre le générateur de fonction à l'extérieur de la boucle -- n'est pas seulement de la Vaisselle, il permet à d'autres personnes qui lisent votre code sais que c'est votre intention.

Si la fonction est en fait la même fonction attribuée à des valeurs différentes dans une itération (ou les objets produits dans une itération), puis au lieu de cela, vous devez assigner la fonction à une variable nommée, et l'utilisation que singulier exemple de la fonction de la mission au sein de la boucle:

handler = function (div_id) {
    return function() { alert(div_id); }
}

for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = handler(div_id);
}

Plus de commentaire/discussion sur ce sujet a été faite par d'autres plus intelligents que moi, quand j'ai posé une question similaire ici sur Stack Overflow: JSlint erreur à Ne pas faire de fonctions à l'intérieur d'une boucle.' mène à la question à propos de Javascript lui-même

Comme pour JSLint: Oui, il est dogmatique et idiomatiques. Cela dit, il est généralement "droit" -- je découvre que beaucoup de beaucoup de gens qui vocaliser négativement sur JSLint fait de ne pas comprendre les subtilités de Javascript, qui sont nombreux et obtus.

7voto

Evan Trimboli Points 15857

JSLint n'est qu'un guide, il n'est pas toujours nécessaire de respecter les règles. Le fait est que vous ne créez pas de fonctions dans une boucle dans le sens auquel elle fait référence. Vous créez uniquement vos classes une fois dans votre application, pas encore et encore.

5voto

jevon Points 1162

Si vous utilisez JQuery, vous voudrez peut-être faire quelque chose comme ceci dans une boucle:

 for (var i = 0; i < 100; i++) {
  $("#button").click(function() {
    alert(i);
  });
}
 

Pour satisfaire JSLint, une façon de contourner ce problème consiste (dans JQuery 1.4.3+) à utiliser l'argument de données de gestionnaire supplémentaire pour .click() :

 function new_function(e) {
  var data = e.data; // from handler
  alert(data); // do whatever
}

for (var i = 0; i < 100; i++) {
  $("#button").click(i, new_function);
}
 

3voto

Matt Eberts Points 21

Déplacez simplement votre bloc (function (name, func) {...}) () en dehors de la boucle et assignez-le à une variable, comme:

var makeFn = fonction (nom, fonction) {...};

Puis dans la boucle ont:

prototype [prop] = makeFn (...)

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