Jaki jest zakres zmiennych w JavaScript?

Jaki jest zakres zmiennych w javascript? Czy mają ten sam zakres wewnątrz, a nie na zewnątrz funkcji? Czy to ma znaczenie? Ponadto, gdzie są przechowywane zmienne, jeśli są zdefiniowane globalnie?

Author: John Slegers, 2009-02-01

26 answers

Myślę, że najlepsze, co mogę zrobić, to dać ci kilka przykładów do przestudiowania. Programiści Javascript są praktycznie uszeregowani według tego, jak dobrze rozumieją zakres. Czasami może to być dość intuicyjne.

  1. Zmienna globalnie skalowana

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. Zasięg lokalny

    // global scope
    var a = 1;
    
    function two(a) { // passing (a) makes it local scope
      alert(a); // alerts the given argument, not the global value of '1'
    }
    
    // local scope again
    function three() {
      var a = 3;
      alert(a); // alerts '3'
    }
    
  3. Intermediate: nie ma czegoś takiego jak zakres bloków w JavaScript (ES5; ES6 wprowadza let)

    A.

    var a = 1;
    
    function four() {
      if (true) {
        var a = 4;
      }
    
      alert(a); // alerts '4', not the global value of '1'
    }
    

    B.

    var a = 1;
    
    function one() {
      if (true) {
        let a = 4;
      }
    
      alert(a); // alerts '1' because the 'let' keyword uses block scoping
    }
    
  4. Intermediate: właściwości obiektu

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  5. Zaawansowane: Zamknięcie

    var a = 1;
    
    var six = (function() {
      var a = 6;
    
      return function() {
        // JavaScript "closure" means I have access to 'a' in here,
        // because it is defined in the function in which I was defined.
        alert(a); // alerts '6'
      };
    })();
    
  6. Zaawansowane: prototypowa rozdzielczość zakresu

    var a = 1;
    
    function seven() {
      this.a = 7;
    }
    
    // [object].prototype.property loses to
    // [object].property in the lookup chain. For example...
    
    // Won't get reached, because 'a' is set in the constructor above.
    seven.prototype.a = -1;
    
    // Will get reached, even though 'b' is NOT set in the constructor.
    seven.prototype.b = 8;
    
    alert(new seven().a); // alerts '7'
    alert(new seven().b); // alerts '8'
    

  7. Globalny + lokalny: bardzo skomplikowana sprawa

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    To wydrukuje undefined i 10 zamiast 5 i 10 ponieważ JavaScript zawsze przenosi deklaracje zmiennych (nie inicjalizacje) na górę zakresu, czyniąc kod równoważny:

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
    
  8. Catch klauzula-zmienna scoped

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    

    To zostanie wydrukowane 5, 6, 5. Wewnątrz klauzuli catch e cienie zmiennych globalnych i lokalnych. Ale ten specjalny zakres jest tylko dla złapanej zmiennej. Jeśli napiszesz var f; wewnątrz klauzuli catch, to będzie dokładnie tak samo, jak gdybyś miał zdefiniowano go przed lub po bloku try-catch.

 2305
Author: Triptych,
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
2018-08-20 10:07:51

Javascript używa łańcuchów zakresu do ustalenia zakresu dla danej funkcji. Zazwyczaj istnieje jeden globalny zakres, a każda zdefiniowana funkcja ma swój własny zagnieżdżony zakres. Każda funkcja zdefiniowana w ramach innej funkcji ma zasięg lokalny, który jest powiązany z funkcją zewnętrzną. To zawsze pozycja w źródle określa zakres.

Element w łańcuchu zakresu jest w zasadzie mapą ze wskaźnikiem do jego nadrzędnego zakresu.

Podczas rozwiązywania zmiennej javascript zaczyna się od najskrytszy zakres i szuka Na Zewnątrz.

 222
Author: krosenvold,
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-08-14 07:54:06

Zmienne deklarowane globalnie mają zasięg globalny. Zmienne zadeklarowane w funkcji są przypisane do tej funkcji i cieniowane zmienne globalne o tej samej nazwie.

(jestem pewien, że istnieje wiele subtelności, które prawdziwi Programiści JavaScript będą w stanie wskazać w innych odpowiedziach. W szczególności natknąłem się na tę stronę o tym, co dokładnie this oznacza w każdej chwili. Mam nadzieję, że Ten bardziej wprowadzający link wystarczy, aby zacząć.)

 96
Author: Jon Skeet,
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
2014-02-25 18:12:12

Old school JavaScript

Tradycyjnie, JavaScript tak naprawdę ma tylko dwa rodzaje zakresu:

  1. zasięg globalny : zmienne są znane w całej aplikacji, Od początku aplikacji (*)
  2. zakres funkcjonalny : zmienne są znane w funkcja są deklarowane w, Od początku funkcji (*)

Nie będę się nad tym rozwodził, ponieważ są już wiele innych odpowiedzi wyjaśniających różnicę.


Nowoczesny JavaScript

The najnowsze specyfikacje JavaScript teraz pozwala również na trzeci zakres:

  1. zakres blokowy : zmienne są znane w blok są deklarowane w, od momentu zgłoszenia (**)

Jak utworzyć zmienne zakresu bloków?

Tradycyjnie tworzysz swoje zmienne takie jak:

var myVariable = "Some text";

Zmienne zakresu bloków są tworzone w następujący sposób:

let myVariable = "Some text";

Jaka jest więc różnica między zakresem funkcjonalnym a zakresem blokowym?

Aby zrozumieć różnicę między zakresem funkcjonalnym a zakresem bloku, rozważ następujący kod:

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

Tutaj widzimy, że nasza zmienna j jest znana tylko w pierwszej pętli for, ale nie przed i po. Jednak nasza zmienna i jest znana w całej funkcji.

Także, należy wziąć pod uwagę, że zmienne o zasięgu blokowym nie są znane przed ich zadeklarowaniem, ponieważ nie są podnoszone. Nie można również ponownie zadeklarować tej samej zmiennej o zasięgu bloku w tym samym bloku. To sprawia, że zmienne o zasięgu blokowym są mniej podatne na błędy niż zmienne o zasięgu globalnym lub funkcjonalnym, które są podnoszone i które nie powodują żadnych błędów w przypadku wielu deklaracji.


Czy używanie zmiennych zakresu blokowego jest dziś bezpieczne?

Czy jest bezpieczny w użyciu dzisiaj zależy od otoczenia:

  • Jeśli piszesz kod JavaScript po stronie serwera (węzeł.js), możesz bezpiecznie używać let.

  • Jeśli piszesz kod JavaScript po stronie klienta i używasz transpilera (jak Traceur), możesz bezpiecznie używać instrukcji let, jednak Twój kod prawdopodobnie nie będzie optymalny pod względem wydajności.

  • Jeśli piszesz po stronie klienta Kod JavaScript i nie używaj transpilera, musisz rozważyć obsługę przeglądarki.

    Dzisiaj, 23 lutego 2016, są to niektóre przeglądarki, które albo nie obsługują let, albo mają tylko częściowe wsparcie:

    • Internet explorer 10 i poniżej (bez wsparcia)
    • Firefox 43 i poniżej (bez wsparcia)
    • [[16]} Safari 9 i poniżej (bez wsparcia)
    • Opera Mini 8 i poniżej (bez wsparcia)
    • Android browser 4 i poniżej (bez wsparcia)
    • Opera 36 i poniżej (częściowe wsparcie)
    • Chome 51 i poniżej (częściowe wsparcie)

Tutaj wpisz opis obrazka


Jak śledzić obsługę przeglądarki

Aby uzyskać aktualny przegląd przeglądarek, które obsługują oświadczenie let w momencie czytania tej odpowiedzi, zobacz this Can I Use page.


(*) globalnie i funkcjonalnie zmienne mogą być inicjowane i używane przed ich zadeklarowaniem, ponieważ zmienne JavaScript są hoisted. oznacza to, że deklaracje są zawsze na szczycie zakresu.

(**) zmienne o zasięgu blokowym nie są podnoszone

 57
Author: John Slegers,
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
2018-03-06 22:25:33

Oto przykład:

<script>

var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested
  };

  anotherGlobal = {
    //global because there's no `var`
  }; 

}

</script>

Będziesz chciał zbadać zamknięcia i jak je wykorzystać, aby stworzyć członków prywatnych .

 35
Author: geowa4,
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
2009-02-01 08:48:09

Kluczem, jak rozumiem, jest to, że Javascript ma zakres poziomu funkcji w porównaniu z bardziej powszechnym zakresem bloku C.

Oto dobry artykuł na ten temat.

 28
Author: James McMahon,
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-05-15 17:38:30

W "Javascript 1.7" (rozszerzenie Mozilli do Javascript) można również zadeklarować zmienne typu block-scope z let oświadczenie :

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4
 23
Author: kennytm,
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-04-06 11:19:39

[1]}idea scopingu w JavaScript, gdy pierwotnie zaprojektowany przez Brendan Eich pochodzi z HyperCard języka skryptowego HyperTalk.

W tym języku wyświetlacze były podobne do stosu kart indeksowych. Była karta główna, zwana tłem. Była przezroczysta i może być postrzegana jako dolna karta. Każda zawartość tej karty bazowej była dzielona z kartami umieszczonymi na niej. Każda karta umieszczona na górze miała swoją zawartość, która miała pierwszeństwo przed poprzednią kartą, ale nadal miał dostęp do poprzednich kart w razie potrzeby.

Tak właśnie zaprojektowany jest system obsługi JavaScript. Ma tylko inne nazwy. Karty w JavaScript są znane jako konteksty wykonania ECMA. Każdy z tych kontekstów zawiera trzy główne części. Środowisko zmienne, środowisko leksykalne i to Wiązanie. Wracając do referencji kart, środowisko leksykalne zawiera wszystkie treści z wcześniejsze karty obniżają się w stosie. Bieżący kontekst znajduje się na szczycie stosu, a zadeklarowana tam zawartość będzie przechowywana w środowisku zmiennej. Środowisko zmiennej będzie miało pierwszeństwo w przypadku kolizji nazw.

To powiązanie będzie wskazywało na obiekt zawierający. Czasami zakres lub konteksty wykonawcze zmieniają się bez zmiany obiektu zawierającego, na przykład w zadeklarowanej funkcji, gdzie obiekt zawierający może być window lub konstruktorem funkcja.

Te konteksty wykonawcze są tworzone za każdym razem, gdy kontrola jest przenoszona. Kontrola jest przekazywana, gdy kod zaczyna się wykonywać, i odbywa się to przede wszystkim z wykonania funkcji.

Więc to jest TECHNICZNE Wyjaśnienie. W praktyce należy pamiętać, że w JavaScript
  • Lunety są technicznie "kontekstami wykonawczymi"
  • konteksty tworzą stos środowisk, w których przechowywane są zmienne
  • Góra stosu ma pierwszeństwo (the bottom being the global context)
  • Każda funkcja tworzy kontekst wykonania (ale nie zawsze nowe to powiązanie)]}

Zastosowanie tego do jednego z poprzednich przykładów (5 . "Closure") na tej stronie można śledzić stos kontekstów wykonania. W tym przykładzie na stosie znajdują się trzy konteksty. Są one definiowane przez kontekst zewnętrzny, kontekst bezpośrednio wywołanej funkcji wywołanej przez var six oraz kontekst zwracanej funkcji wewnątrz var natychmiast wywołana funkcja six.

i ) kontekst zewnętrzny. Ma zmienne środowisko o = 1
ii) kontekst IIFE, ma środowisko leksykalne a = 1, ale środowisko zmienne a = 6, które ma pierwszeństwo w stosie
iii ) zwracany kontekst funkcji, ma środowisko leksykalne a = 6 i jest to wartość, do której odwołuje się alert podczas wywołania.

Tutaj wpisz opis obrazka

 18
Author: Travis J,
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
2015-09-14 20:29:53

1) istnieje globalny zakres, zakres funkcji oraz zakresy with I catch. Nie ma ogólnego zakresu poziomu 'block' dla zmiennych -- polecenia with I catch dodają nazwy do swoich bloków.

2) zakresy są zagnieżdżane przez funkcje aż do globalnego zakresu.

3) właściwości są rozwiązywane przez przejście przez łańcuch prototypów. Instrukcja with przenosi nazwy właściwości obiektów do zakresu leksykalnego zdefiniowanego przez blok with.

EDIT: ECMAAScript 6 (Harmony) jest spec'ed do obsługi let, i Wiem, że chrome pozwala na flagę 'harmony' , więc być może to obsługuje..

Let będzie wsparciem dla przeszukiwania na poziomie bloków, ale musisz użyć słowa kluczowego, aby tak się stało.

EDIT: bazując na wskazówkach Benjamina z I catch wypowiedzi w komentarzach, edytowałem post i dodałem więcej. Zarówno instrukcje with, jak i catch wprowadzają zmienne do swoich odpowiednich bloków, a jest zakresem bloku. Te zmienne są aliasowane do właściwości przekazywanych do nich obiektów.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

EDIT: Clarifying example:

Test1 jest scopowany do bloku with, ale jest aliasowany do a. test1. 'Var test1' tworzy nową zmienną test1 w górnym kontekście leksykalnym (function lub global), chyba że jest to właściwość -- którą jest.

Yikes! Bądź ostrożny używając 'with' -- tak jak var jest noop jeśli zmienna jest już zdefiniowana w funkcji, jest również noop w odniesieniu do nazw importowane z obiektu! Trochę uwagi na temat już zdefiniowanej nazwy uczyniłoby to o wiele bezpieczniejszym. Ja osobiście nigdy z tego nie skorzystam.
 16
Author: Gerard ONeill,
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
2014-06-06 17:13:06

Odkryłem, że wiele osób, które są nowicjuszami JavaScript, ma problemy ze zrozumieniem, że dziedziczenie jest domyślnie dostępne w języku i że zakres funkcji jest jak dotąd jedynym zakresem. Podałem rozszerzenie do upiększacza, który napisałem pod koniec zeszłego roku o nazwie JSPretty. Zakres funkcji kolory funkcji w kodzie i zawsze kojarzy kolor ze wszystkimi zmiennymi zadeklarowanymi w tym zakresie. Zamknięcie jest wizualnie pokazane, gdy zmienna o kolorze z jednego zakresu jest używana w innym zakres.

Wypróbuj funkcję na:

Zobacz demo na:

Wyświetl kod na stronie:

Obecnie funkcja oferuje obsługę głębokości 16 zagnieżdżonych funkcji, ale obecnie nie koloruje zmiennych globalnych.

 9
Author: austincheney,
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
2013-03-21 17:31:11

JavaScript ma tylko dwa rodzaje zakresu:

  1. Zakres Globalny : Zakres Globalny jest niczym innym jak zakresem poziomu okna.Tutaj zmienna obecna w całej aplikacji.
  2. zakres funkcjonalny : zmienna zadeklarowana w funkcji za pomocą słowa kluczowego var ma zakres funkcjonalny.

za każdym razem, gdy wywołana jest funkcja, tworzony jest obiekt zakresu zmiennej (i zawarty w łańcuchu zakresu), po którym następują zmienne w JavaScript.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

Scope chain -- >

  1. Poziom okna - a i outer Funkcje znajdują się na najwyższym poziomie w łańcuchu zakresu.
  2. gdy zewnętrzna funkcja nazywa się nową variable scope object (i zawiera się w łańcuchu zakresu) dodaną ze zmienną b wewnątrz niej.

Teraz, gdy wymagana jest zmienna a, najpierw wyszukuje najbliższy zakres zmiennej i jeśli zmienna nie istnieje, to przenosi się do następnego obiektu łańcucha zmiennej zakresu.w tym przypadku jest to poziom okna.

 8
Author: Anshul,
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
2014-09-21 20:49:17

Aby dodać do innych odpowiedzi, scope jest listą wszystkich zadeklarowanych identyfikatorów( zmiennych)i wymusza ścisły zestaw reguł, jak są one dostępne dla aktualnie wykonującego kod. To szukanie może być w celu przypisania zmiennej, która jest odniesieniem LHS (lefthand-side), lub może być w celu pobrania jej wartości, która jest odniesieniem RHS (righthand-side). Te poszukiwania są tym, co silnik JavaScript robi wewnętrznie, gdy jest kompilowanie i wykonywanie kodu.

Więc z tej perspektywy, myślę, że zdjęcie pomogłoby, że znalazłem w lunety i zamknięcia Ebook Kyle Simpson:

obraz

Cytowanie z ebooka:

Budynek reprezentuje zagnieżdżony zestaw reguł naszego programu. Pierwszy piętro budynku reprezentuje aktualnie wykonywany zakres, gdziekolwiek jesteś. Najwyższym poziomem budynku jest zasięg globalny. Rozwiązujesz referencje LHS i RHS przez patrząc na aktualną podłogę, a jeśli go nie znajdziesz, weź windę na następne piętro. , patrząc tam, potem dalej, i tak dalej. Po dotarciu na najwyższe piętro (zakres globalny), albo znajdziesz to, czego szukasz, albo ale i tak musisz przestać.

Warto wspomnieć o jednej rzeczy: "szukanie Scope zatrzymuje się, gdy znajdzie pierwsze dopasowanie".

Ta idea "poziomów zakresu" wyjaśnia, dlaczego "to" można zmienić za pomocą nowo utworzonego zakres, jeśli jest sprawdzany w zagnieżdżonej funkcji. Oto link, który wchodzi w te wszystkie szczegóły, Wszystko, co chciałeś wiedzieć o javascript scope

 8
Author: James Drinkard,
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-03-30 13:33:04

Uruchom kod. mam nadzieję, że to da pomysł na scoping

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);
 7
Author: Yeasin Abedin Siam,
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
2014-10-18 09:54:56

Zasięg Globalny:

Zmienne globalne są dokładnie takie same jak gwiazdy globalne (Jackie Chan, Nelson Mandela). Możesz uzyskać do nich dostęp (pobrać lub ustawić wartość), z dowolnej części aplikacji. Funkcje globalne są jak globalne wydarzenia (Nowy Rok, Boże Narodzenie). Można je wykonywać (wywoływać) z dowolnej części aplikacji.
//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

Zasięg Lokalny:

Jeśli jesteś w USA, możesz znać Kim Kardashian, niesławną celebrytkę (jakoś udaje jej się zrobić tabloidy). Ale ludzie poza USA jej nie rozpozna. Jest lokalną gwiazdą, związaną ze swoim terytorium. Zmienne lokalne są jak gwiazdy lokalne. Możesz uzyskać do nich dostęp (pobrać lub ustawić wartość) tylko wewnątrz zakresu. Funkcja lokalna jest podobna do lokalnych zdarzeń - możesz wykonywać tylko (celebrować) wewnątrz tego zakresu. Jeśli chcesz uzyskać do nich dostęp spoza zakresu, otrzymasz błąd odniesienia
function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

Sprawdź ten artykuł, aby uzyskać dogłębne zrozumienie zakresu

 7
Author: KhanSharp,
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-02-23 18:56:04

Istnieją prawie tylko dwa rodzaje zakresów JavaScript:

  • zakres każdej deklaracji var jest związany z najbardziej natychmiastową funkcją
  • jeśli nie ma funkcji zamykającej dla deklaracji var, jest to zasięg globalny

Tak więc bloki inne niż funkcje nie tworzą nowego zakresu. To wyjaśnia, dlaczego for-loops nadpisuje zewnętrzne zmienne o zasięgu:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

Używanie funkcji zamiast:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

W pierwszym przykładzie nie było zakres blokowy, więc wstępnie zadeklarowane zmienne zostały nadpisane. W drugim przykładzie pojawił się nowy zakres ze względu na funkcję, więc początkowo zadeklarowane zmienne były cieniowane, a nie nadpisywane.

To prawie wszystko, co musisz wiedzieć w zakresie JavaScript scoping, z wyjątkiem:

Więc można zobaczyć JavaScript scoping jest rzeczywiście bardzo proste, choć nie zawsze intuicyjne. Kilka rzeczy, o których warto pamiętać:

  • deklaracje var są podnoszone do góry zakresu. Oznacza to, że bez względu na to, gdzie ma miejsce deklaracja var, dla kompilatora jest tak, jakby sam var miał miejsce na górze
  • wiele deklaracji var w ramach tego samego scope are combined

Więc ten kod:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

Jest równoważne:

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);
To może wydawać się sprzeczne z intuicją, ale ma sens z perspektywy imperatywnego projektanta języka.
 5
Author: jackbean818,
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
2015-10-29 16:12:19

Nowoczesne Js, ES6+, "const " i 'let'

Powinieneś używać zakresów blokowych dla każdej zmiennej, którą tworzysz, tak jak większość innych głównych języków. var jest przestarzałe. Dzięki temu Twój kod jest bezpieczniejszy i łatwiejszy do utrzymania.

const należy stosować do 95% przypadków . To sprawia, że zmienna reference nie może się zmienić. Właściwości węzła Array, object i Dom mogą się zmieniać i prawdopodobnie powinny być const.

let należy stosować dla każdej zmiennej spodziewam się przeniesienia. Obejmuje to pętlę for. Jeśli kiedykolwiek zmienisz wartość poza inicjalizacją, użyj let.

Zakres blokowy oznacza, że zmienna będzie dostępna tylko w nawiasach, w których jest zadeklarowana. Obejmuje to wewnętrzne zakresy, w tym anonimowe funkcje utworzone w Twoim zakresie.

 5
Author: Gibolt,
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-12-08 19:03:40

W JS są tylko zakresy funkcji. Nie blokuj celowników! Widać też, co się podnosi.

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);
 4
Author: koredalin,
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
2015-07-11 18:13:01

Każdy fragment kodu JavaScript (globalny kod lub funkcje) ma powiązany z nim łańcuch zakresu. Zakres łańcuch jest listą lub łańcuchem obiektów, który definiuje zmienne, które są "w zakresie" dla tego kod. Gdy JavaScript musi wyszukać wartość zmiennej x (proces o nazwie zmienna rozdzielczość ), zaczyna się od spojrzenia na pierwszy obiekt w łańcuchu. Jeśli obiekt ten ma właściwość o nazwie x, wartość tej właściwości jest używana. Jeśli pierwszy obiekt nie ma a właściwość o nazwie x, JavaScript kontynuuje wyszukiwanie z następnym obiektem w łańcuchu. Jeśli drugi obiekt nie posiada właściwości o nazwie x, wyszukiwanie przechodzi do następnego obiekt, i tak dalej. Jeśli {[0] } nie jest własnością żadnego z obiektów w łańcuchu zakresu, to x nie ma zakresu dla tego kodu i występuje ReferenceError. W kodzie JavaScript najwyższego poziomu (tj. kod Nie zawarty w żadnej definicji funkcji), łańcuch scope składa się z jednego obiektu, globalnego obiektu. W funkcja bez zagnieżdżenia, łańcuch scope składa się z dwóch obiektów. Pierwszy to obiekt, który definiuje funkcję parametry i zmienne lokalne, a drugi to obiekt globalny. W funkcji zagnieżdżonej, łańcuch scope ma trzy lub więcej obiektów. Ważne jest, aby zrozumieć, w jaki sposób ten łańcuch obiektów jest tworzony. Gdy funkcja jest zdefiniowana , przechowuje łańcuch zakresu w efekcie. Gdy ta funkcja jest wywoływana , tworzy nowy obiekt do przechowywania swoich zmiennych lokalnych, oraz dodaje ten nowy obiekt do przechowywanego łańcucha zakresu, aby utworzyć nowy, dłuższy łańcuch, który reprezentuje zakres wywołania tej funkcji. To staje się bardziej interesujące dla funkcji zagnieżdżonych, ponieważ za każdym razem, gdy wywołana jest funkcja zewnętrzna, funkcja wewnętrzna jest zdefiniowany ponownie. Ponieważ łańcuch zakresu różni się przy każdym wywołaniu funkcji zewnętrznej, funkcja wewnętrzna będzie subtelnie inna za każdym razem, gdy zostanie zdefiniowana-kod wewnętrznej funkcja będzie identyczna przy każdym wywołaniu funkcja zewnętrzna, ale łańcuch zakresu powiązany z tym kodem będzie inny . To pojęcie łańcucha zakresu ma kluczowe znaczenie dla zrozumienia zamknięć.

 4
Author: Fanyo SILIADIN,
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-01-28 11:16:18

Wypróbuj ten ciekawy przykład. W poniższym przykładzie, jeśli a jest liczbą zainicjalizowaną na 0, zobaczysz 0, a następnie 1. Z tym, że a jest obiektem, a javascript przekaże f1 wskaźnik a zamiast jego kopię. W rezultacie otrzymujesz ten sam alert za każdym razem.

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());
 3
Author: Mig82,
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
2013-08-10 17:37:14

Rozumiem, że istnieją 3 zakresy: globalny zakres, dostępny globalnie; lokalny zakres, Dostępny dla całej funkcji niezależnie od bloków; i zakres blokowy, dostępny tylko dla bloku, instrukcji lub wyrażenia, na którym został użyty. Globalny i lokalny zakres jest oznaczany słowem kluczowym 'var', wewnątrz funkcji lub na zewnątrz, a zakres bloku jest oznaczany słowem kluczowym 'let'.

Dla tych, którzy wierzą, że istnieje tylko globalny i lokalny zasięg, Proszę wyjaśnić, dlaczego Mozilla będzie miała całą stronę opisującą niuanse zakresu bloków w JS.

Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

 3
Author: mrmaclean89,
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-09-16 22:35:07

W JavaScript istnieją dwa rodzaje zakresu:

  • zasięg lokalny
  • zasięg globalny

Poniższa funkcja posiada zmienną local scope carName. I ta zmienna nie jest dostępna z zewnątrz funkcji.

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

Poniższa klasa ma globalną zmienną zakresu carName. I ta zmienna jest dostępna z każdego miejsca w klasie.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}
 2
Author: Abdur Rahman,
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-11-01 09:16:18

W EcmaScript5 są głównie dwa zakresy, local scope i global scope , ale w EcmaScript6 mamy głównie trzy zakresy, local scope, global scope oraz nowy zakres o nazwie Block scope .

Przykład zakresu bloku to:-

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}
 1
Author: Vivek Mehta,
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-12-15 07:49:36

ECMAScript 6 wprowadził słowa kluczowe let i const. Te słowa kluczowe mogą być użyte zamiast słowa kluczowego var. W przeciwieństwie do słowa kluczowego var, słowa kluczowe let i const obsługują deklarację lokalnego zakresu wewnątrz instrukcji blokowych.

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10
 1
Author: Dava E.,
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
2018-02-09 15:37:12

ES5 i starsze:

Zmienne w Javascript były początkowo (pre ES6) leksykalnie funkcyjne. Termin leksykalnie Ograniczony oznacza, że możesz zobaczyć zakres zmiennych, "patrząc" na kod.

Każda zmienna zadeklarowana za pomocą słowa kluczowego var jest przypisana do funkcji. Jeśli jednak w obrębie tej funkcji zadeklarowane zostaną inne Funkcje, Funkcje te będą miały dostęp do zmiennych funkcji zewnętrznych. To się nazywa łańcuch zakresu. Działa w następujący sposób:

  1. gdy funkcja szuka wartości zmiennej, najpierw patrzy na własny zakres. Jest to ciało funkcji, czyli wszystko pomiędzy nawiasami klamrowymi {} (z wyjątkiem zmiennych wewnątrz Inne funkcje, które znajdują się w tym zakresie).
  2. jeśli nie może znaleźć zmiennej wewnątrz ciała funkcji, to wejdzie do łańcucha i spojrzy na zakres zmiennej w funkcji w , gdzie funkcja została zdefiniowana . To jest to, co oznacza zakres leksykalny, możemy zobaczyć w kodzie, gdzie ta funkcja została zdefiniowana, a tym samym możemy określić łańcuch zakresu, patrząc tylko na kod.

Przykład:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

Co się dzieje, gdy próbujemy zarejestrować zmienne foo, bar, i foobar do konsoli jest następujący:

  1. próbujemy zalogować foo do konsoli, foo można znaleźć wewnątrz samej funkcji innerFunc. Dlatego wartość foo jest rozdzielana na ciąg innerFunc.
  2. staramy się logować pasek do konsoli, paska nie można znaleźć wewnątrz samej funkcji innerFunc. Dlatego musimy wspiąć się na łańcuch lunety . Najpierw przyjrzymy się zewnętrznej funkcji, w której zdefiniowano funkcję innerFunc. Jest to funkcja outerFunc. W zakresie outerFunc możemy znaleźć zmienną bar, która zawiera łańcuch 'outerFunc'.
  3. foobar nie może być znaleziony w innerFunc. . Dlatego musimy wspiąć się na łańcuch scope do innerFunc zakres. Nie można go również znaleźć tutaj, wspinamy się na kolejny poziom do globalnego zakresu (tj. najbardziej oddalonego zakresu). Znajdujemy tu zmienną foobar, która posiada łańcuch 'global'. Jeśli nie znalazłby zmiennej po wejściu na łańcuch zakresu, silnik JS rzuciłby referenceError .

ES6 (ES 2015) i starsze:

Te same pojęcia zakresu leksykalnego i scopechain nadal obowiązują w ES6. Jednak nowe sposoby deklarowania zmiennych były przedstawiam. Są następujące:

  • let: tworzy zmienną o zasięgu bloku
  • const: tworzy zmienną o zasięgu blokowym, która musi być zainicjalizowana i nie może być ponownie przypisana

Największa różnica między var A let/const jest to, że var jest zakresem funkcji, podczas gdy let/const są zablokowane. Oto przykład, aby to zilustrować:

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

W powyższym przykładzie letVar zapisuje wartość global, ponieważ zmienne zadeklarowane przez let mają zakres blokowy. Przestają istnieć poza danym blokiem, więc zmienna nie może być dostępna poza blokiem if.

 0
Author: Willem van der Veen,
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
2018-09-30 09:23:31

Istnieją dwa rodzaje zakresów w JavaScript.

  1. Global scope : zmienna ogłoszona w global scope może być używana w dowolnym miejscu programu bardzo płynnie. Na przykład:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
    
  2. Functional scope lub Local scope: zmienna zadeklarowana w tym zakresie może być używana tylko w jej własnej funkcji. Na przykład:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
    
 -2
Author: A. Randhawa,
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-01-11 05:32:02

Global: zmienna zadeklarowana poza funkcją

Local: zmienna zadeklarowana wewnątrz funkcji i może być wywołana tylko w tym zakresie

 -3
Author: poisonlocc,
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
2015-01-03 19:35:52