Jak naprawić błąd jslint ' nie rób funkcji w pętli.'?

Pracuję nad tym, aby cały nasz kod JS przeszedł przez jslint, czasami z wieloma poprawkami z opcjami, aby uzyskać legacy code pass Na teraz z zamiarem poprawienia go później.

Jest jedna rzecz, na którą jslint narzeka, że nie mam obejścia. To jest przy użyciu konstruktów takich jak ten, otrzymujemy błąd ' Don ' t make functions within a loop.'

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]);
    }
}

Pętla ta jest częścią implementacji js dziedziczenia klasycznego, gdzie klasy rozszerzające istniejące klasy zachowują super Właściwość klasy rozszerzonej podczas wywoływania członka klasy rozszerzonej. Dla jasności, powyższa implementacja jest inspirowana tym postem na blogu autorstwa Johna Resiga.

Ale mamy również inne instancje funkcji utworzonych w pętli.

Jedynym obejściem jak dotąd jest wyłączenie tych plików JS z jslint, ale chcielibyśmy użyć jslint do sprawdzania poprawności kodu i sprawdzania składni w ramach naszej ciągłej integracji i zbudować przepływ pracy.

Czy jest lepszy sposób na zaimplementowanie takiej funkcjonalności, czy też istnieje sposób na poprawienie kodu poprzez jslint?

Author: Rishabh, 2010-06-14

6 answers

Douglas Crockford ma nowy idiomatyczny sposób osiągnięcia powyższego - jego stara technika polegała na użyciu wewnętrznej funkcji do wiązania zmiennych, ale nowa technika używa Kreatora funkcji. Zobacz slide 74 w slajdach do jego" funkcji ostateczny " talk . [Ten slideshare już nie istnieje]

Dla leniwych, oto kod:

function make_handler(div_id) {
    return function () {
        alert(div_id);
    };
}
for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = make_handler(div_id);
}
 66
Author: Skilldrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-22 16:20:24

(natknąłem się na te pytania wiele miesięcy po opublikowaniu...)

Jeśli tworzysz funkcję w pętli, instancja funkcji jest tworzona dla każdej iteracji pętli. O ile funkcja, która jest tworzona, jest w rzeczywistości inna dla każdej iteracji, to użyj metody umieszczania Generatora funkcji poza pętlą - robiąc to nie jest tylko sztuczka, pozwala innym, którzy czytają Twój kod, wiedzieć, że to był twój zamiar.

Jeśli funkcja jest rzeczywiście tą samą funkcją przypisanie do różnych wartości w iteracji( lub obiektów wytworzonych w iteracji), zamiast tego musisz przypisać funkcję do nazwanej zmiennej i użyć tej pojedynczej instancji funkcji w przypisaniu w pętli:

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

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

Większy komentarz/dyskusja na ten temat została wykonana przez innych mądrzejszych ode mnie, gdy postawiłem podobne pytanie tutaj na Stack Overflow: błąd JSlint ' nie tworzy funkcji w pętli."prowadzi do pytania o Javascript itself

Co do JSLint: Tak, to jest dogmatyczne i idiomatyczne. To powiedziawszy, zwykle jest to "prawo" - odkrywam, że wiele wielu ludzi, którzy wokalizują negatywnie o JSLint, w rzeczywistości nie rozumie (subtelności) Javascript, które są liczne i rozwarte.

 12
Author: Zhami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:20

Dosłownie, uzyskaj wokół problemu, wykonując następujące czynności:

  1. Create a .jshintrc Plik
  2. Dodaj następujący wiersz do pliku .jshintrc

    {"loopfunc" : true, // tolerate functions being defined in loops }

 11
Author: lifebalance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-03 17:56:44

JSLint jest tylko przewodnikiem, nie zawsze musisz przestrzegać zasad. Chodzi o to, że nie tworzysz funkcji w pętli w sensie, do którego się odnosi. Klasy tworzysz tylko raz w aplikacji, a nie w kółko.

 7
Author: Evan Trimboli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-14 13:40:54

Jeśli używasz JQuery, możesz zrobić coś takiego w pętli:

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

Aby zaspokoić JSLint, jednym ze sposobów obejścia tego problemu jest (w JQuery 1.4.3+) użycie dodatkowego argumentu obsługi danych do .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);
}
 5
Author: jevon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-20 00:36:32

Just move your:

(function (name, func) {...})()

Zablokuj pętlę i przypisz ją do zmiennej, np.:

var makeFn = function(name, func){...};

Następnie w pętli mają:

prototype[prop] = makeFn(...)

 3
Author: Matt Eberts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-18 09:50:57