2011-08-06 21 views
32

Czy zmienne są zadeklarowane i przypisane w wyrażeniu "jeśli" widoczne tylko w tym bloku "jeśli" lub w całej funkcji?Zakres zmiennej javascript w instrukcji IF

Czy robię to dobrze w poniższym kodzie? (wydaje się działać, ale deklarowanie "struktury var" wielokrotnie wydaje się niezręczne) żadnych czystszych rozwiązań?

function actionPane(state) { 
    if(state === "ed") { 
     var structure = { 
      "element" : "div", 
      "attr" : { 
       "class" : "actionPane" 
      }, 
      "contains" : [{ 
       "element" : "a", 
       "attr" : { 
        "title" : "edit", 
        "href" : "#", 
        "class" : "edit" 
       }, 
       "contains" : "" 
      }, { 
       "element" : "a", 
       "attr" : { 
        "title" : "delete", 
        "href" : "#", 
        "class" : "delete" 
       }, 
       "contains" : "" 
      }] 
     } 
    } else { 
     var structure = { 
      "element" : "div", 
      "attr" : { 
       "class" : "actionPane" 
      }, 
      "contains" : [{ 
       "element" : "a", 
       "attr" : { 
        "title" : "save", 
        "href" : "#", 
        "class" : "save" 
       }, 
       "contains" : "" 
      }, { 
       "element" : "a", 
       "attr" : { 
        "title" : "cancel", 
        "href" : "#", 
        "class" : "cancel" 
       }, 
       "contains" : "" 
      }] 
     } 
    } 
    return structure; 
} 
+0

Zauważ, że możesz to również zrobić: 'if (state ===" ed ") {return {...}} else {return {...}}' zamiast użycia zmiennej. –

Odpowiedz

35

1) Variables are visible for the whole function scope. Dlatego powinieneś zadeklarować je tylko raz.

2) Nie powinieneś zadeklarować zmiennej dwukrotnie w twoim przykładzie. Polecam deklarując zmienną w górnej części funkcji, a potem po prostu ustawiając wartość później:

function actionPane(state) { 
    var structure; 
    if(state === "ed") { 
     structure = {  
      ... 

Dla doskonałą opinię na temat JavaScriptu, bardzo polecam korzystania JSLint Douglas Crockforda. Przeszuka Twój kod pod kątem typowych błędów i znajdzie sugestie dotyczące czyszczenia.

Polecam również przeczytać małą książkę JavaScript: The Good Parts. Zawiera wiele wskazówek dotyczących pisania obsługiwanego kodu JS.

+0

@WebWanderer - dotyczy tylko ES6, co jest niesamowite, ale wymaga użycia kompilatora po stronie klienta. ES5 i starsze nie obsługują niczego poza zasięgiem globalnym lub na poziomie funkcjonalnym. – OverZealous

+0

Myślę, że wszyscy używają JSHint zamiast JSLint teraz dni. –

+0

@KevinWheeler Jest to dość stara odpowiedź, ale każdy, kto pracuje na ES6 lub nowszym, będzie dużo lepiej wyemigrował do [ESLint] (http://eslint.org/). – OverZealous

31

JavaScript nie ma „zasięg blokowy”, to tylko ma zakres funkcji - tak zmienne zadeklarowane wewnątrz if (lub dowolny blok warunkowy) są „podnoszony” do zakresu zewnętrznej.

if(true) { 
    var foo = "bar"; 
} 
alert(foo); // "bar" 

To faktycznie maluje jaśniejszy obraz (i pojawia się w wywiadach z doświadczenia :)

var foo = "test"; 
if(true) { 
    alert(foo); // Interviewer: "What does this alert?" Answer: "test" 
    var foo = "bar"; 
} 
alert(foo); // "bar" Interviewer: Why is that? Answer: Because JavaScript does not have block scope 

zakres funkcji, w JavaScript, zazwyczaj odnosi się do zamknięć.

var bar = "heheheh"; 
var blah = (function() { 
    var foo = "hello"; 
    alert(bar); // "heheheh" 
    alert(foo); // "hello" (obviously) 
}); 

blah(); // "heheheh", "hello" 
alert(foo); // undefined, no alert 

Wewnętrzny zasięg funkcji ma dostęp do środowiska, w którym się znajduje, ale nie na odwrót.

Aby odpowiedzieć na drugie pytanie, optymalizację można uzyskać, początkowo konstruując "minimalny" obiekt, który spełnia wszystkie warunki, a następnie rozszerzając go lub modyfikując w oparciu o określone warunki, które zostały spełnione.

+6

Javascript ma zasięg bloku. Możesz zadeklarować zmienną w ciągu 'instrukcji if' używając' let myVar = "Najpierw sprawdź!" [Sprawdź słowo kluczowe let] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statement/let) – WebWanderer

+0

@WebWanderer let jest prawie nieobsługiwany tutaj w grudniu 2015 roku, ta odpowiedź została opublikowana w sierpniu 2011. – trex005

+0

@ trex005 Tak, rozumiem. Technicznie rzecz biorąc, nie jest to jeszcze obsługiwane, ale będzie z ECMA 6. Mój komentarz nie dotyczy OP, który nie znalazł odpowiedzi w ciągu ponad czterech lat, ale zamiast tego dla innych przechodzących przez ten post zastanawia się, jak to zrobić teraz. Weź moją uwagę jako myślenie życzeniowe. – WebWanderer

2

Zmienne zadeklarowane w instrukcji if będą dostępne tak długo, jak długo będą znajdować się w tej samej funkcji.

W twoim przypadku, najlepszym sposobem byłoby zadeklarować strukturę, a następnie zmodyfikować części obiektu, które różnią się w obu przypadkach:

var structure = { 
    "element" : "div", 
    "attr" : { 
     "class" : "actionPane" 
    }, 
    "contains" : [{ 
     "element" : "a", 
     "attr" : { 
      "title" : "edit", 
      "href" : "#", 
      "class" : "edit" 
     }, 
     "contains" : "" 
    }, { 
     "element" : "a", 
     "attr" : { 
      "title" : "delete", 
      "href" : "#", 
      "class" : "delete" 
     }, 
     "contains" : "" 
    }] 
} 

if(state != "ed") { 
    // modify appropriate attrs of structure (e.g. set title and class to cancel) 
} 
2

są zmienne zadeklarowane i przypisane w „if” widoczny tylko w obrębie tego bloku "if" lub w obrębie całej funkcji?

w JavaScript, wszystkie zmienne są albo

  • zasięg globalny
  • zasięg lokalny (cały funkcja) - Javascript nie ma „zasięg blokowy”, gdzie dostępne są tylko z zmienne mniejszy blok lokalnego zakresu (funkcja)

Czy robię to dobrze w poniższym kodzie? (wydaje się działać, ale zadeklarowanie "var structure" kilka razy wydaje się akwarde) jakichkolwiek czystszych rozwiązań ?

Tak. Czyściejszym rozwiązaniem może być zbudowanie klasy bazowej structure i modyfikacja tego, co jest w każdym przypadku różne.

+0

JavaScript nie ma klas. –

+1

@Tomalak: JavaScript * ma *, jednak mają obiekty, które są porównywalne do klas. – foxy

+0

JavaScript ma obiekty. Ale jego model OOP jest oparty na prototypach, _nie_ na klasie. –

3

ECMAScript 2015 (ES6) zawiera dwie nowe słowa kluczowe, które ostatecznie pozwalają JavaScript, żeby dokonać właściwego scopingu bloku bez konieczności korzystania obejście, potocznej składni:

  1. let
  2. const