Jaki jest cel słowa kluczowego var i kiedy należy go używać (lub pomijać)?

UWAGA: to pytanie zostało zadane z punktu widzenia ECMAScript w wersji 3 lub 5. Odpowiedzi mogą stać się nieaktualne wraz z wprowadzeniem nowych funkcji w wersji ECMAScript 6.

Jaka jest dokładnie funkcja słowa kluczowego var w JavaScript i jaka jest między nimi różnica

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

I

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

?

Kiedy użyłbyś któregoś z nich i dlaczego/co to robi?


person Alex    schedule 24.09.2009    source źródło
comment
Czy podczas łączenia deklaracji var umieszczenie znaku nowej linii po przecinku wpływa na zachowanie? var x=1, y=2, [powrót]z=3;   -  person Alfabravo    schedule 20.11.2011
comment
Nieużycie var naraża Cię również na wypadek, gdyby wybrana nazwa zmiennej była wcześniej zdefiniowaną zmienną globalną. Zobacz moją podróż żałoby tutaj: stackoverflow.com/questions/16704014/   -  person Scott C Wilson    schedule 23.05.2013
comment
Wpis na blogu @Ray Toal meloncard (zdecydowanie warty przeczytania) został przeniesiony na blog.safeshepherd.com/23/how-one-missing-var-ruined-our-launch   -  person Hephaestus    schedule 02.03.2014
comment
Nigdy nie wyobrażałem sobie, że wiersz może zainspirować mnie do rozważenia problemu programowego   -  person Félix Adriyel Gagnon-Grenier    schedule 15.03.2015
comment
Zamiast tego użyj const i let! var nie jest nowoczesnym JS   -  person Gibolt    schedule 15.08.2017
comment
@Gibolt, ale spójrz na datę pytania, to trochę niesprawiedliwe wezwanie pytania z 2009 roku, aby to powiedzieć. Mimo że jest on nadal aktualny pod względem łatwości konserwacji, istnieje kilka nienowoczesnych kodów JS.   -  person Andre Figueiredo    schedule 16.03.2018
comment
Mam nadzieję, że ktoś czytający mój komentarz, który jest nowy w JS (prawdopodobnie jeśli tego szuka), nauczy się wcześnie. To, że istnieje nienowoczesny kod, nie oznacza, że ​​powinniśmy go nadal przedstawiać jako poprawną odpowiedź   -  person Gibolt    schedule 16.03.2018
comment
Pamiętaj, że we współczesnym JavaScript zwykle powinieneś używać let zamiast var (ze względu na różnice w zachowaniu let i var).   -  person Quentin    schedule 19.12.2019


Odpowiedzi (19)


Jeśli jesteś w zasięgu globalnym, nie ma dużej różnicy. Przeczytaj odpowiedź Kangax w celu wyjaśnienia

Jeśli korzystasz z funkcji, var utworzy zmienną lokalną, „no var” będzie przeszukiwać łańcuch zasięgu, dopóki nie znajdzie zmiennej lub nie osiągnie zasięgu globalnego (w tym momencie ją utworzy ):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

Jeśli nie robisz zadania, musisz użyć var:

var x; // Declare x
person Greg    schedule 24.09.2009
comment
Czy naprawdę nie ma dużej różnicy == Żadnej różnicy? - person Alex; 24.09.2009
comment
Cóż, właściwie tak, jest różnica :) Czy ta różnica jest istotna, to już inna kwestia. Zobacz moją odpowiedź niżej: stackoverflow.com/questions/1470488/ - person kangax; 25.09.2009
comment
Myślę, że o to właśnie chodzi Alexowi i dlatego napisał to za pomocą operatora równa się! - person James Bedford; 13.09.2012
comment
To jak strzelanie do siebie z działa szynowego... Zapomnij o umieszczeniu „var” przed zmienną, a skończysz na modyfikowaniu zmiennej gdzieś w łańcuchu zasięgu... Spróbuj przekonać Java/C/Pythona /itp. programiście, że JavaScript jest tego wart. Ha! Dla kontrastu pułapki C/C++ wyglądają ładnie. Wyobraź sobie, że musisz debugować JavaScript... I oczywiście niektórzy ludzie to robią. I jest tak dużo kodu (i nie jest to prosty kod, pamiętaj) napisanego w JavaScript... - person Albus Dumbledore; 24.02.2013
comment
Jeśli działasz w zakresie globalnym, nie ma różnicy. ›› istnieje różnica, którą wyjaśniono w odpowiedzi poniżej - person Max Koretskyi; 13.09.2013
comment
@Alex 0 == false, więc tak, niezbyt duża różnica == Brak różnicy, ale niezbyt duża różnica!== Brak różnicy - person Math chiller; 14.11.2013
comment
Jeśli jesteś w trybie ścisłym, nawet w zakresie globalnym, będziesz potrzebować var, aby to zadeklarować. - person Juan Mendes; 15.11.2013
comment
jeśli „użyjesz strict”;, powinieneś użyć var. - person WarFox; 24.03.2014
comment
jest to ważne, jeśli chcesz zachować publiczne elementy interfejsu API/prywatne elementy wzorca modułu. Niezbędne jest zrozumienie, że var umieści obiekty w lokalnym zasięgu modułu. Dziękuję za wyjaśnienie. warto również zauważyć, jeśli mam rację, funkcja x() jest równoważna var x = funkcja () i różni się od x = funkcja () w odniesieniu do zakresu. - person ferr; 10.09.2014
comment
Bardzo dziękuję. Walczę z tym od wieków, potem przeczytałem ten wiersz: „Jeśli korzystasz z funkcji, wówczas var utworzy zmienną lokalną, żaden var nie będzie przeszukiwał łańcucha zasięgu, dopóki nie znajdzie zmiennej lub nie osiągnie zasięgu globalnego ( w którym momencie to utworzy)” - doskonałe wyjaśnienie, dzięki. - person developerbmw; 04.02.2015
comment
co masz na myśli, mówiąc o utworzeniu zamknięcia? - person NuWin; 31.07.2016
comment
To duża różnica: zmienne zadeklarowane za pomocą var istnieją przed rozpoczęciem wykonywania, a te, których nie ma, nie istnieją, dopóki nie zostanie wykonana instrukcja, która je utworzyła. Ponadto tych zadeklarowanych za pomocą var nie można usunąć, podczas gdy te, które nie są, są usuwalnymi właściwościami obiektu globalnego. Ponadto funkcja anonimowa tworzy domknięcia wszystkich zmiennych zewnętrznych, a nie tylko globalnych (tzn. ma domknięcie na foo, bar i muu. - person RobG; 07.11.2017
comment
Zobacz także stackoverflow.com/questions/38270470/ dla interesującego przykładu bardziej subtelnej różnicy między obiema deklaracjami. - person Mihai Târnovan; 28.09.2018
comment
Zwrot ...w którym momencie to utworzy ma bardzo niejednoznaczne sformułowanie - moje pytanie wciąż pozostaje nierozwiązane. Czy ten punkt jest powiązany z przepływem logicznym? (np. nie znaleziono nigdzie, więc utworzono.. lokalnie) Czy też punkt jest powiązany z zakresem, w którym tworzona jest zmienna? (np. zmienna przeszukiwana aż do zasięgu globalnego, nawet tam nie znaleziona, więc tam utworzona). Czy mógłbyś to trochę przeformułować, proszę? - person xakepp35; 21.10.2018
comment
W przypadku kodu C++ wynik int i=1; { cout<<i; int i=2; cout<<i; } cout<<i; będzie następujący: 121. Czy jest to zachowanie mniej var czy var? - person xakepp35; 21.10.2018

Jest różnica.

var x = 1 deklaruje zmienną x w bieżącym zakresie (czyli kontekście wykonania). Jeżeli deklaracja występuje w funkcji - deklarowana jest zmienna lokalna; jeśli ma zasięg globalny - deklarowana jest zmienna globalna.

x = 1 jest natomiast jedynie przeniesieniem własności. Najpierw próbuje rozwiązać x względem łańcucha zasięgu. Jeśli znajdzie go gdziekolwiek w tym łańcuchu zasięgu, wykonuje przypisanie; jeśli nie znajdzie x, dopiero wtedy tworzy właściwość x na obiekcie globalnym (który jest obiektem najwyższego poziomu w łańcuchu zasięgu).

Teraz zauważ, że nie deklaruje zmiennej globalnej, tworzy właściwość globalną.

Różnica między nimi jest subtelna i może być myląca, chyba że zrozumiesz, że deklaracje zmiennych tworzą również właściwości (tylko w obiekcie Variable) i że każda właściwość w JavaScript (no cóż, ECMAScript) ma pewne flagi opisujące ich właściwości - ReadOnly, DontEnum i DontDelete.

Ponieważ deklaracja zmiennej tworzy właściwość z flagą DontDelete, różnica pomiędzy var x = 1 i x = 1 (gdy jest wykonywana w zakresie globalnym) polega na tym, że pierwsza - deklaracja zmiennej - tworzy właściwość DontDelete'able, a druga nie. W rezultacie właściwość utworzoną poprzez to niejawne przypisanie można następnie usunąć z obiektu globalnego, natomiast tej pierwszej, utworzonej poprzez deklarację zmiennej, nie można usunąć.

Ale to oczywiście tylko teoria i w praktyce różnic między nimi jest jeszcze więcej z powodu różnych błędów w implementacjach (takich jak te z IE).

Mam nadzieję, że to wszystko ma sens :)


[Aktualizacja 2010/12/16]

W ES5 (ECMAScript 5; niedawno ujednolicony, 5. wydanie języka) istnieje tak zwany „tryb ścisły” — tryb języka opcjonalny, który nieznacznie zmienia zachowanie niezadeklarowanych przypisań. W trybie ścisłym przypisanie do niezadeklarowanego identyfikatora jest ReferenceError. Powodem tego było wyłapanie przypadkowych przypisań, zapobiegając tworzeniu niepożądanych właściwości globalnych. Niektóre z nowszych przeglądarek rozpoczęły już obsługę trybu ścisłego. Zobacz na przykład moją tabelę zgodności.

person kangax    schedule 24.09.2009
comment
Jeśli dobrze pamiętam, myślę, że kiedyś znalazłem sposób, aby móc delete zmienną zadeklarowaną za pomocą var za pomocą eval hacka. Jeśli pamiętam dokładnie tę sztuczkę, opublikuję ją tutaj. - person Tower; 30.06.2011
comment
@Mageek Być może chodzi o zmienne zadeklarowane przez eval, które można usunąć. Kiedyś napisałem post na blogu. - person kangax; 20.06.2012
comment
Trochę nie na temat, ale wspominam o tym tutaj w celach informacyjnych. let jest bardzo podobny do var i jest obsługiwany w Mozilli. Główna różnica polega na tym, że zakresem zmiennej var jest cała otaczająca funkcja, gdzie as let jest ograniczone do swojego bloku - person mac; 01.10.2012
comment
@kangax co by było, gdyby dwie ostatnie linijki przykładów Alexa zostały zmieszane: var someObject = {} i someObject.someProperty = 5? Czy someProperty stałby się globalny, podczas gdy obiekt, którego jest własnością, pozostałby lokalny? - person snapfractalpop; 28.11.2012
comment
Nazwa specyfikacji tego, co @kangax nazywa flagą DontDelete, jest konfigurowalna (= false), możesz o tym przeczytać w odniesieniu do Object.defineProperty i Object.getOwnPropertyDescriptor - person Paul S.; 08.01.2014
comment
w niektórych wersjach IE występuje błąd umożliwiający usunięcie deklaracji zmiennej w zasięgu globalnym - person Shiala; 19.12.2014
comment
@Shiala Pamiętam coś takiego. Myślę, że tylko ze zmiennymi, które cieniują (mają taką samą nazwę jak) wbudowane globalne, ale nie jestem pewien. - person kangax; 19.12.2014
comment
Nie jestem teraz w pobliżu komputera, ale jeśli pamięć mi służy, wypróbowałem to z var x = 0; i IE nie powstrzymało mnie przed usunięciem. - person Shiala; 19.12.2014
comment
Byłoby miło zobaczyć dodatkową aktualizację tej odpowiedzi, która szczegółowo opisuje, w jaki sposób let wpływa na pytanie dotyczące PO. - person Snekse; 24.09.2015
comment
@Snekse let nie wpływa na x = 1 część odpowiedzi, więc jedyna różnica dotyczy var x = 1 i let x = 1. Zostało to udokumentowane wiele razy w wielu miejscach, ale 2 główne różnice są takie, że let ma zasięg blokowy i tworzy TDZ (tymczasową martwą strefę), co oznacza, że ​​nie można go używać ani nawet odwoływać się do niego przed deklaracją. - person kangax; 29.09.2015
comment
@kangax Rozumiem. Mówię tylko, że jeśli ktoś, kto nigdy nawet nie słyszał o let, natknie się na tę odpowiedź, dobrze byłoby po prostu wspomnieć o let i podać link do innego źródła informacji, aby mógł przeczytać. - person Snekse; 29.09.2015

Twierdzenie, że jest to różnica między „lokalnym a globalnym”, nie jest do końca trafne.

Lepiej byłoby pomyśleć o tym jako o różnicy między „lokalnym a najbliższym”. Najbliższy z pewnością może mieć charakter globalny, ale nie zawsze tak będzie.

/* global scope */
var local = true;
var global = true;

function outer() {
    /* local scope */
    var local = true;
    var global = false;

    /* nearest scope = outer */
    local = !global;

    function inner() {
        /* nearest scope = outer */
        local = false;
        global = false;

        /* nearest scope = undefined */
        /* defaults to defining a global */
        public = global;
    }
}
person Jonathan Lonowski    schedule 24.09.2009
comment
Czy najbliższy zakres nie jest outer tam, gdzie definiujesz var global = false;? - person Snekse; 19.04.2013
comment
@Snekse: „najbliższy” nie ma zastosowania, gdy zadeklarowano ‹code›var global = false;‹/code›. W tej deklaracji element „global” znajduje się w zakresie funkcji external(), ponieważ w deklaracji użyto elementu „var”. Ponieważ wartość „var” nie jest używana w funkcji internal(), zmieni ona wartość na wyższym poziomie, czyli na poziomie zewnętrznym(). - person Mitch; 18.09.2015
comment
Zastanawiam się, czy Twój komentarz zmieniłby się, gdybyś zmienił tę linię na var global = local;, w którym to przypadku najbliższy zakres lokalnego byłby aktywnie definiowanym lokalnym zakresem zewnętrznym. Chociaż może się to wydawać dziwne, jeśli zmienisz tę samą linię na var global = global, w którym to przypadku najbliższy zakres podczas wyszukiwania wartości global będzie wyższy o poziom globalnego zakresu okna. - person Snekse; 24.09.2015

Kiedy JavaScript jest wykonywany w przeglądarce, cały kod jest otoczony instrukcją with, na przykład:

with (window) {
    //Your code
}

Więcej informacji na temat with - MDN

Ponieważ var deklaruje zmienną w bieżącym zakresie , nie ma różnicy pomiędzy zadeklarowaniem var wewnątrz okna a jej całkowitym brakiem.

Różnica pojawia się, gdy nie znajdujesz się bezpośrednio w oknie, np. przy oknie. wewnątrz funkcji lub wewnątrz bloku.

Użycie var pozwala ukryć zmienne zewnętrzne o tej samej nazwie. W ten sposób możesz symulować zmienną „prywatną”, ale to inny temat.

Ogólna zasada jest taka, aby zawsze używać var, ponieważ w przeciwnym razie istnieje ryzyko wprowadzenia subtelnych błędów.

EDYCJA: Po otrzymanej krytyce chciałbym podkreślić, co następuje:

  • var deklaruje zmienną w bieżącym zakresie
  • Zasięg globalny to window
  • Nieużywanie var domyślnie deklaruje var w zakresie globalnym (okno)
  • Deklarowanie zmiennej w zasięgu globalnym (oknie) przy użyciu var jest równoznaczne z jej pominięciem.
  • Deklarowanie zmiennej w zakresach innych niż okno przy użyciu var to nie to samo, co deklarowanie zmiennej bez var
  • Zawsze deklaruj var wyraźnie, ponieważ jest to dobra praktyka
person kentaromiura    schedule 24.09.2009
comment
Nie głosowałem na ciebie, ale zakres jest prawdopodobnie lepszym słowem niż okno. Całe twoje wyjaśnienie jest trochę tępe. - person Robert Harvey; 25.09.2009
comment
Ja po prostu nazywam rzeczy po nazwie, ty chcesz to nazwać zasięgiem globalnym, jest ok, ale po stronie klienta, zgodnie z konwencją, jest obiekt okna, czyli ostatni element łańcucha zasięgu, dlatego możesz wywołać każdą funkcję i każdy obiekt w oknie bez okna zapisu. - person kentaromiura; 25.09.2009
comment
+1 to naprawdę niezłe wyjaśnienie — nie słyszałem wcześniej omówionego w ten sposób problemu var/no var (bez zamierzonej gry słów). - person doug; 10.04.2012
comment
Większość tej odpowiedzi jest przestarzała z let w ES6. - person Evan Carroll; 21.01.2014
comment
@EvanCarroll Ta odpowiedź jest również niepoprawna technicznie, ponieważ pominięcie var nie deklaruje żadnej zmiennej, zamiast tego tworzy usuwalną właściwość na obiekcie globalnym, poza tym, że w ES5 używa się trybu ścisłego, większość odpowiedzi jest oczywiście niepoprawna, niech nawet nie było rozważone w tej odpowiedzi, ponieważ w momencie pytania nie było żadnego odniesienia do wersji javascript (dodanej wczoraj), co oznaczałoby, że standardem odniesienia (w tamtym czasie) była ECMA 262, wydanie 3. - person kentaromiura; 22.01.2014
comment
Stwierdzenie cały kod jest otoczony instrukcją with jest po prostu błędne. Gdyby to była prawda, nazwy zmiennych zostałyby rozwiązane w obiekcie okna przed zasięgiem lokalnym. - person RobG; 07.11.2017

Do deklarowania zmiennych zawsze używaj słowa kluczowego var. Dlaczego? Dobra praktyka kodowania powinna być wystarczającym powodem sama w sobie, ale pominięcie jej oznacza, że ​​jest ona zadeklarowana w zakresie globalnym (taka zmienna nazywana jest „implikowaną” wartością globalną). Douglas Crockford zaleca, aby nigdy nie używać domyślnych wartości globalnych i zgodnie z Wskazówki dotyczące kodowania JavaScript firmy Apple:

Każda zmienna utworzona bez słowa kluczowego var jest tworzona w zasięgu globalnym i nie jest wyrzucana do śmieci, gdy funkcja powraca (ponieważ nie wykracza poza zakres), co stwarza możliwość wycieku pamięci.

person Steve Harrison    schedule 24.09.2009
comment
Dobra praktyka kodowania nigdy nie powinna być wystarczającym powodem sama w sobie. Sprowadza się do tego, że niektórzy goście w Internecie powiedzieli, że tak powinien wyglądać mój kod. Jest to nawet mniej ważne, niż powiedział mój nauczyciel, chyba że ktoś przynajmniej niejasno rozumie przyczynę tej reguły. - person cHao; 24.05.2013
comment
@cHao Myślę, że good coding practice jest zawsze wystarczającym powodem, jeśli jest to zalecana najlepsza praktyka, którą jest i kilku autorów JavaScript. - person Chris S; 03.01.2014
comment
@ChrisS: Nie, dobra praktyka kodowania nie jest powodem sama w sobie. Liczy się powód, dla którego jest to uważane za dobrą praktykę. Jeśli ci autorzy nie powiedzą Ci, dlaczego to polecają, ich rekomendacja nie powinna mieć żadnego znaczenia. Jeśli nie zgadzasz się z powodami, możesz uznać to za złą radę. A jeśli będziesz się tym kierować, nigdy nie pytając dlaczego, tak właśnie zaczyna się kult cargo. - person cHao; 03.01.2014

Oto całkiem dobry przykład tego, jak można zostać przyłapanym na niezadeklarowaniu zmiennych lokalnych za pomocą var:

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

(i jest resetowany przy każdej iteracji pętli, ponieważ nie jest deklarowany lokalnie w pętli for, ale globalnie) ostatecznie skutkuje nieskończoną pętlą

person Chris S    schedule 24.09.2009
comment
Tak! Mogę sobie tylko wyobrazić wszystkie błędy, które mogą być spowodowane tą literówką. - person BonsaiOak; 13.10.2014
comment
ciekawi mnie, dlaczego przekazujesz i jako argument do two()? (wewnątrz pętli for) czy to jest zbędne? - person kalin; 03.10.2016
comment
Argument jest ignorowany w funkcji two() zawartej w funkcji one(), ponieważ funkcja two() została zdefiniowana bez parametru. Masz rację, nie jest to potrzebne, ponieważ nie odgrywa żadnej roli. - person KK.; 24.02.2017
comment
Błąd czy funkcja? - person TheMaster; 25.08.2019

Powiedziałbym, że w większości sytuacji lepiej jest używać var.

Zmienne lokalne są zawsze szybsze niż zmienne o zasięgu globalnym.

Jeśli nie użyjesz var do zadeklarowania zmiennej, zmienna będzie miała zasięg globalny.

Aby uzyskać więcej informacji, możesz wyszukać w Google „łańcuch zasięgu JavaScript”.

person Billy    schedule 24.09.2009
comment
Jeśli zadeklarujesz zmienną za pomocą słowa kluczowego var, zostanie ona utworzona w czasie wykonywania, więc czy nie powinna być wolniejsza? Ponieważ inny jest tworzony w czasie analizy. - person Barış Velioğlu; 14.08.2012
comment
@RyuKaplan – hej, czy to prawda? Próbowałem googlować i nie znalazłem żadnych informacji na ten temat! Czy masz źródło potwierdzające tę tezę? Dzięki - person mike rodent; 12.04.2013
comment
@RyuKaplan Analiza/kompilacja różni się od faktycznego uruchomienia kodu. - person gcampbell; 08.07.2016

Nie używaj var!

var był sposobem deklarowania zmiennej w wersji wcześniejszej niż ES6. Jesteśmy teraz w przyszłości i powinieneś kodować jako taki.

Użyj const i let

const powinno być używane w 95% przypadków. Sprawia to, że odwołanie do zmiennej nie może się zmienić, a zatem właściwości tablicy, obiektu i węzła DOM mogą się zmienić i prawdopodobnie powinny wynosić const.

let należy zastosować w przypadku każdej zmiennej, która ma zostać ponownie przypisana. Obejmuje to pętlę for. Jeśli kiedykolwiek napiszesz varName = poza inicjalizacją, użyj let.

Oba mają zakres na poziomie bloku, zgodnie z oczekiwaniami w większości innych języków.

person Gibolt    schedule 15.08.2017
comment
Zamień wszystkie „var” na „const” (zamień wszystko). Szybko zauważysz, gdzie znajdują się ponownie przypisane zmienne. Jeśli masz ich zbyt wiele, prawdopodobnie kodujesz antywzorcowo: większość zmiennych, które można ponownie przypisać, można osadzić w domknięciach lub jako właściwości obiektu. Jeśli masz kilka: użyj dla nich „let”. Wreszcie, jeśli niektóre zmienne nie zostaną w ogóle zadeklarowane za pomocą „var”, pozostaną niezadeklarowane i nadal będą obecne w przestrzeni globalnej, uważaj. O komentarzu @Gibolta „w pętli for” zaleca się również unikanie takich pętli w 95% przypadków ;-): metody tablicowe są świetne. - person allez l'OM; 21.10.2018
comment
Mówiąc, że const powinno być stosowane w 95% przypadków, wydaje się, że odchodzimy od dobrych praktyk i kierujemy się w stronę dogmatów. - person Agamemnus; 28.12.2018

kolejna różnica, np

var a = a || [] ; // works 

chwila

a = a || [] ; // a is undefined error.
person Pranay Warke    schedule 09.08.2013
comment
Czy mógłbyś wyjaśnić, dlaczego to działa w przypadku zmiennej zdefiniowanej za pomocą „var” i zmiennej niezdefiniowanej za pomocą var? Czy zmienna jest tworzona przed oceną prawej strony przypisania w przypadku var? - person matt; 05.12.2013
comment
@Lucek, ponieważ var a jest podnoszony na górę zakresu i ustawiony na null, co deklaruje, ale nie inicjuje zmiennej, wówczas w przypisaniu masz odwołanie do niezdefiniowanej zmiennej null, która ma wartość false i ustawia przypisanie na []. W tym drugim przypadku masz przypisanie do właściwości a właściwości a. Możesz przypisać do właściwości, która nie istnieje - tworząc ją przy przypisaniu, ale nie możesz czytać właściwości, która nie istnieje, bez otrzymania ReferenceError. - person Evan Carroll; 20.01.2014
comment
@EvanCarroll: zostaje podniesiony na szczyt zakresu i ustawiony na niezdefiniowany zamiast zerowego. - person Mithun Satheesh; 25.09.2014

Użycie var jest zawsze dobrym pomysłem, aby zapobiec zaśmiecaniu zakresu globalnego przez zmienne i wzajemnym konfliktom zmiennych, powodującym niepożądane nadpisywanie.

person kevinji    schedule 04.04.2011

Bez var - zmienna globalna.

Zdecydowanie zaleca się, aby ZAWSZE używać instrukcji var, ponieważ inicjowanie zmiennej globalnej w kontekście lokalnym jest złe. Ale jeśli potrzebujesz tej brudnej sztuczki, powinieneś napisać komentarz na początku strony:

/* global: varname1, varname2... */
person Anatoliy    schedule 24.09.2009

Oto przykładowy kod, który napisałem, aby zrozumieć tę koncepcję:

var foo = 5; 
bar = 2;     
fooba = 3;

// Execute an anonymous function
(function() {    
    bar = 100;             //overwrites global scope bar
    var foo = 4;           //a new foo variable is created in this' function's scope
    var fooba = 900;       //same as above
    document.write(foo);   //prints 4
    document.write(bar);   //prints 100
    document.write(fooba); //prints 900
})();

document.write('<br/>');
document.write('<br/>');
document.write(foo);       //prints 5
document.write(bar);       //prints 100
document.write(fooba);     //prints 3
person Community    schedule 27.10.2013
comment
Funkcja nie jest w żadnym wypadku anonimowa. W rzeczywistości jest tak wyraźnie nazwany, jak to tylko możliwe. - person Ingo Bürk; 23.01.2014
comment
Dziękujemy za edytowanie odpowiedzi w odpowiedzi na komentarz Ingo Bürka, aby funkcja anonimowa była rzeczywiście anonimowa. - person Dave Burton; 09.09.2016

@Chris S podał ładny przykład pokazujący praktyczną różnicę (i niebezpieczeństwo) między var a nr var. Oto kolejny przypadek. Ten uważam za szczególnie niebezpieczny, ponieważ różnica jest widoczna tylko w środowisku asynchronicznym, więc może łatwo przemknąć podczas testowania.

Jak można się spodziewać, następujące wyniki fragmentu kodu ["text"]:

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

Podobnie wygląda następujący fragment (zwróć uwagę na brakujące let przed array):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

Asynchroniczne wykonanie manipulacji danymi nadal daje ten sam wynik przy użyciu jednego modułu wykonującego:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

Ale zachowuje się inaczej w przypadku wielu:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

Używając jednak let:

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

person thisismydesign    schedule 29.12.2017
comment
Dziękuję za przykład @thisismydesign! Jeśli chodzi o dwa ostatnie przykłady, dlaczego przedostatni przykład rejestruje tablicę składającą się z 3 elementów z tekstem zapisanym trzykrotnie, podczas gdy ostateczny przykład rejestruje tekst tylko raz na element w tablicy? (Rozumiem, że ostatni deklaruje tablicę jako zmienną i dlatego ma zasięg lokalny, podczas gdy przedostatni przykład pomija to, czyniąc tablicę częścią sugerowanego zakresu globalnego). Ale dlaczego wpływa to na wynik? Czy dzieje się tak dlatego, że forEach i wykonuje iterację po funkcji i wszystkich zmiennych globalnych? - person Brad Ahrens; 22.09.2019

Jako ktoś, kto próbuje się tego nauczyć, tak to widzę. Powyższe przykłady były może nieco zbyt skomplikowane dla początkującego.

Jeśli uruchomisz ten kod:

var local = true;
var global = true;


function test(){
  var local = false;
  var global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Dane wyjściowe będą brzmiały: fałsz, fałsz, prawda, prawda

Ponieważ widzi zmienne w funkcji jako oddzielne od tych na zewnątrz, stąd termin zmienna lokalna, a to dlatego, że użyliśmy var w przypisaniu. Jeśli usuniesz var z funkcji, teraz będzie ona brzmiała tak:

var local = true;
var global = true;


function test(){
  local = false;
  global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Dane wyjściowe to fałsz, fałsz, fałsz, fałsz

Dzieje się tak dlatego, że zamiast tworzyć nową zmienną w zakresie lokalnym lub funkcji, po prostu używa zmiennych globalnych i ponownie przypisuje im wartość false.

person Danrex    schedule 01.10.2016

Widzę, że ludzie są zdezorientowani podczas deklarowania zmiennych z var lub bez niej, wewnątrz lub na zewnątrz funkcji. Oto szczegółowy przykład, który przeprowadzi Cię przez następujące kroki:

Zobacz poniższy skrypt w działaniu tutaj w jsfiddle

a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");

function testVar1(){
    c = 1;// Defined inside the function without var
    var d = 1;// Defined inside the function with var
    alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};


testVar1();
alert("Run the 1. function again...");
testVar1();

function testVar2(){
    var d = 1;// Defined inside the function with var
    alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);

Wniosek

  1. Bez względu na to, czy są zadeklarowane z var czy bez (np. a, b), jeśli uzyskają swoją wartość poza funkcją, zachowają swoją wartość, a także wszelkie inne wartości dodane do różnych funkcji za pomocą skryptu zostaną zachowane.
  2. Jeśli zmienna zostanie zadeklarowana bez var wewnątrz funkcji (np. c), będzie działać jak poprzednia reguła, od tej chwili zachowa swoją wartość we wszystkich funkcjach. Albo otrzymał swoją pierwszą wartość w funkcji testVar1(), nadal zachowuje tę wartość i otrzymuje dodatkową wartość w funkcji testVar2()
  3. Jeśli zmienna jest zadeklarowana z var tylko wewnątrz funkcji (np. d w testVar1 lub testVar2), będzie ona niezdefiniowana za każdym razem, gdy funkcja się zakończy. Będzie to zatem zmienna tymczasowa w funkcji.
person Tarik    schedule 20.11.2016
comment
Dziękujemy za poświęcenie czasu na utworzenie przykładu ilustrującego ten temat. W powyższym kodzie brakuje poniższej części, więc możesz chcieć edytować swoją odpowiedź: a = 1;// Zdefiniowane poza funkcją bez var var b = 1;// Zdefiniowane poza funkcją z var alert (Zaczynając od wszystkich funkcji. .. \n \n a, b zdefiniowane, ale c, d jeszcze nie zdefiniowane: \n a: + a + \n b: + b + \n \n (Jeśli próbuję pokazać wartość niezdefiniowanego c lub d, console. log wygeneruje błąd „Uncaught ReferenceError: c nie jest zdefiniowany” i skrypt przestanie działać!)); - person Sankofa; 11.10.2018

Wewnątrz kodu, jeśli używasz zmiennej bez użycia var, wtedy dzieje się automatycznie, że var nazwa_zmiennej jest umieszczana w zasięgu globalnym, np.:

someFunction() {
    var a = some_value; /*a has local scope and it cannot be accessed when this
    function is not active*/
    b = a; /*here it places "var b" at top of script i.e. gives b global scope or
    uses already defined global variable b */
}
person Akash Arora    schedule 13.08.2013

Oprócz problemu z zakresami niektórzy wspominają także o podnoszeniu, ale nikt nie podał przykładu. Oto jeden dla zasięgu globalnego:

console.log(noErrorCase);
var noErrorCase = "you will reach that point";

console.log(runTimeError);
runTimeError = "you won't reach that point";

person deathangel908    schedule 05.09.2019

Bez użycia „var” zmienne można zdefiniować tylko wtedy, gdy ustawiona jest wartość. W przykładzie:

my_var;

nie może działać w zasięgu globalnym ani żadnym innym zakresie. Powinien mieć wartość taką jak:

my_var = "value";

Z drugiej strony możesz zdefiniować dostępne polubienie;

var my_var;

Jego wartość wynosi undefined (jego wartość nie wynosi null i nie jest równa null, co ciekawe.).

person umut    schedule 27.04.2014
comment
my_var; jest w rzeczywistości prawidłową instrukcją wyrażenia. - person lexicore; 27.11.2014
comment
Jest to poprawna instrukcja, jeśli zmienna została wcześniej zdefiniowana. W przeciwnym razie zgłasza błąd ... nie jest zdefiniowany. - person umut; 27.11.2014
comment
Jest to poprawna instrukcja niezależnie od tego, czy zmienna została wcześniej zdefiniowana, czy nie. :) Prawidłowa instrukcja może spowodować błąd, ale nie powoduje to, że instrukcja jest nieważna. - person lexicore; 27.11.2014
comment
Jestem tym zmieszany. Co jest prawidłowym oświadczeniem? Czy możesz podać mi przykład nieprawidłowego oświadczenia? - person umut; 27.11.2014
comment
Muszę przeprosić - ostatnio za dużo gramatyki ECMAScript. my_var; jest prawidłowym wyrażeniem. /my_var; byłoby nieprawidłowym stwierdzeniem. Ale jak powiedziałem, to kazuistyka gramatyczna, przepraszam, mój komentarz był właściwie niestosowny. - person lexicore; 27.11.2014

Powinieneś użyć słowa kluczowego var, chyba że chcesz mieć zmienną dołączoną do obiektu okna w przeglądarce. Oto link wyjaśniający zakres i różnica między zakresem glokalnym a zakresem lokalnym ze słowem kluczowym var i bez niego.

Kiedy zmienne są definiowane bez użycia słowa kluczowego var, wygląda to na prostą operację „przypisania”.

Kiedy wartość jest przypisana do zmiennej w JavaScript, interpreter najpierw próbuje znaleźć „deklarację zmiennej” w tym samym kontekście/zakresie, co przypisanie. Kiedy interpreter wykonuje dummyVariable = 20, szuka deklaracji dummyVariable na początku funkcji. (Ponieważ wszystkie deklaracje zmiennych są przenoszone na początek kontekstu przez interpreter JavaScript i nazywa się to podnoszeniem)

Możesz także przyjrzeć się podnoszenie javascript

person S Khurana    schedule 12.12.2016