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?
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.
-
Zmienna globalnie skalowana
// global scope var a = 1; function one() { alert(a); // alerts '1' }
-
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' }
-
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 }
-
Intermediate: właściwości obiektu
var a = 1; function Five() { this.a = 5; } alert(new Five().a); // alerts '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' }; })();
-
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'
-
Globalny + lokalny: bardzo skomplikowana sprawa
var x = 5; (function () { console.log(x); var x = 10; console.log(x); })();
To wydrukuje
undefined
i10
zamiast5
i10
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); })();
-
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 catche
cienie zmiennych globalnych i lokalnych. Ale ten specjalny zakres jest tylko dla złapanej zmiennej. Jeśli napiszeszvar f;
wewnątrz klauzuli catch, to będzie dokładnie tak samo, jak gdybyś miał zdefiniowano go przed lub po bloku try-catch.
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.
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ąć.)
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:
- zasięg globalny : zmienne są znane w całej aplikacji, Od początku aplikacji (*)
- 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:
- 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)
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
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 .
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.
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
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.
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.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:
- http://prettydiff.com/lib/jspretty.js
- https://github.com/austincheney/Pretty-Diff/blob/master/lib/jspretty.js
Obecnie funkcja oferuje obsługę głębokości 16 zagnieżdżonych funkcji, ale obecnie nie koloruje zmiennych globalnych.
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:
- Zakres Globalny : Zakres Globalny jest niczym innym jak zakresem poziomu okna.Tutaj zmienna obecna w całej aplikacji.
-
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 -- >
- Poziom okna -
a
iouter
Funkcje znajdują się na najwyższym poziomie w łańcuchu zakresu. - 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.
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:
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
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);
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 odniesieniafunction 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
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:
- try / catch wprowadzenie nowego zakresu tylko dla samej zmiennej wyjątkowej, inne zmienne nie mają nowego zakresu
- with-clause najwyraźniej jest innym wyjątkiem, ale używanie with-clause to wysoce zniechęcony (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with )
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.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.
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);
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ęć.
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());
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
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
}
}
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.
}
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
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:
- 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).
- 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:
- próbujemy zalogować foo do konsoli, foo można znaleźć wewnątrz samej funkcji
innerFunc
. Dlatego wartość foo jest rozdzielana na ciąginnerFunc
. - 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 funkcjaouterFunc
. W zakresieouterFunc
możemy znaleźć zmienną bar, która zawiera łańcuch 'outerFunc'. - 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.
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.
-
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 }
-
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 }
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
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