2013-03-27 14 views
5

nawiązujące do tego tematu: Don't make functions within a loop. - jslint errorjslint - Nie rób funkcji w pętli

Jak można obsługiwać .each jquery (function() {...} w pętli for wiedząc, że potrzebne?

kontekście „za” moim „każdej” funkcji. Oczywiście mogę mapować każdy wymagane parametry do funkcji funkcją deklarowanej na zewnątrz pętli, ale z mojego punktu widzenia oddziaływania na czytelność.

Wszelkie myśli?

Z góry dziękuję

Odpowiedz

4

Th Problem z e funkcji w pętli jest: to,

for (var i = 0; i < list.length; i+= 1) { 
    function my_func(i) { 
     console.log(i); 
    } 
    my_func(i); 
} 

Będzie interpretowana w:

var my_func; 
for (var i = 0; i < list.length; i+= 1) { 
    my_func = function (i) { 
     console.log(i); 
    } 
    my_func(i); 
} 

powodu zmiennej podnosić. Wszystkie deklaracje zostaną przeniesione na początek zakresu (tj. Funkcja). Więc nie ma sensu definiowanie funkcji w pętli for.

Jeśli chcesz połączyć się z licznikiem w pętli for, po prostu zamknij.

Wystarczy być jasne:

$("..").each(function() { 
    for(..) { 
    } 
}); 

jest w porządku.

for(..) { 
    $("..").each(function() { 

    }); 
} 

nie jest w porządku, ponieważ jest to równoznaczne z tym:

var my_func; 
for(..) { 
    my_func = function() { 
     // .. 
    } 
    $("..").each(my_func); 
} 
2

To już brzmi jak problem jest bardziej z ostrzeżeniem niż w kodzie. Tak, będzie miło przejść test JSLint bez ostrzeżeń, ale niektóre z nich mogą być nieuzasadnione i powodować niepotrzebne refaktoryzacje kodu.

Dyskusję w tej Q & A ma znaczenie: Should I use JSLint or JSHint JavaScript validation? Inne narzędzia szarpie dostępne są z większą elastyczność niż JSLint więc można nadal być produktywnym z osobistych preferencji kodowania, niekoniecznie osobistych preferencji kodowania Crockforda użytkownika.

Sugeruję, aby rozważyć użycie innego narzędzia do zawiązania JavaScriptu i nie rezygnować z czytelności lub łatwości obsługi kodu.

+0

Pewnie, ale mimo to zmusza do zadawania dobrych pytań. Komentarz ruffin o tym, że funkcja jest redeclared w kółko, jest z pewnością przyczyną tej reguły, która w końcu ma sens. – y0uri

9

Cóż, możesz zachować kontekst pętli for w pętli, ponieważ wszystko w kodzie jest w tym samym kontekście co funkcja zadeklarowana na początku.

Weźmy więc przykład Fritsa, ale najpierw zróbmy to w pełni JSLint szczęśliwe (minus funkcja wywołana w błędzie pętli).

/*global console*/ 
var my_func, i, list; 
for (i = 0; i < list.length; i+= 1) { 
    my_func = function (i) { 
     console.log(i); 
    }; 
    my_func(i); 
} 

Należy pamiętać, że za każdym razem iteracyjne pętlę, jesteś redeclaring funkcja my_func. To nie fajne! Dlaczego ponownie deklarować tę samą funkcję w kółko?

uznaniu jej wcześniej, tak:

/*global console*/ 
var my_func, i, list; 

my_func = function (i) { 
    console.log(i); 
}; 

for (i = 0; i < list.length; i+= 1) { 
    my_func(i); 
} 

Sukces. Teraz nie tworzysz funkcji z każdą iteracją. I, jak JSLint pomaga uświadomić sobie, przesuwając wszystkie deklaracje var na górę, nadal masz ten sam kontekst.


EDIT: W @Flame points out, nie trzeba zadeklarować funkcję wcześnie z jQuery each i może wykorzystywać anonimową funkcję, ale nie jest to zły pomysł, aby zadeklarować wcześnie, zwłaszcza jeśli robisz do ponownego użycia logiki w wielu połączeniach each. Głównym odbiorcą jest to, aby zrozumieć, że 1.) Praktyka wczesnej deklaracji nadal ma zalety, i 2.) jQuery nadal będzie wysyłać argumenty do twojej funkcji (tutaj, co nazywamy index), chociaż JSLint będzie nie (i nie powinien) narzekać na anonimowe funkcje używane w each s (jQuery sauce here).

Początkowo jest to trochę bardziej nieintuicyjne, jeśli przyzwyczaisz się do konstrukcji anonimowej $.each(function() {});, ale jest to równie proste.

/*global alert, $ */ 
$("li").each(function(index) { 
    alert(index + ": " + $(this).text()); 
}); 

... zamienia się ...

/*global $, alert */ 
var fnOutside = function(index) { 
    alert(index + ": " + $(this).text()); 
}; 
$("li").each(fnOutside); 

To może być mylące, ponieważ krótko wywołanie funkcji nie posiada parametrów, ale jQuery jest co pchanie „indeks” parametr do funkcji . Możesz po prostu chwycić kontekstową tablicę arguments, aby zobaczyć, że nadal jest tam wciśnięta, jeśli chcesz opuścić nazwę.

Fiddle-ige

To znaczy, for konstrukt nie tworzy nowego zamknięcia. To może cię martwić. To nie problem!

+0

masz rację, to jest sposób, aby uczynić jslint szczęśliwym i zachować kod tak czytelny, jak to tylko możliwe. To rozwiązanie, które opisuję, wpływa na czytelność mojego wstępnego pytania. z jednym parametrem jest ok, ale jeśli rozważasz użycie 10 ... – y0uri

+1

Oczywiście, przepraszam za zbyt podstawowe dla twojego pytania. Prawdziwym sednem dla mnie jest pogrubiona część, powyżej, konkretnie, że * deklarowanie w pętli redukuje wydajność * (gdy redeclare za każdym razem tę samą funkcję) i łamie logiczną "normalizację", co jest wystarczającym powodem (imo) do umieszczenia go w nieco bardziej nieczytelny stan, tuż nad 'for'. Zawsze można użyć obiektu złożonego, aby było ono banalnie bardziej czytelne ('options = {var1:" val1 ", var2:" val2 "...}') lub powiązać z czymś użytecznym. Tak czy inaczej, biorę porady JSLint w tych przypadkach. – ruffin

+0

@rufin Może to być mylące na krótko, ponieważ wywołanie funkcji nie ma parametrów, ale jQuery jest tym, co przesuwa parametr "index" do funkcji. jQuery wypycha również drugi parametr, mianowicie element, który może być mniej mylący niż przy użyciu '$ (this) .'/* global $, alert */var fnOutside = funkcja (indeks, el) {alert (indeks +": " + $ (el) .text()); }; $ ("li") .each (fnOutside); – user2720770

Powiązane problemy