UWAGA : Pytanie to zostało zadane z punktu widzenia ECMAScript w wersji 3 lub 5. Odpowiedzi mogą stać się nieaktualne po wprowadzeniu nowych funkcji w wydaniu ECMAScript 6.
Jaka dokładnie jest funkcja var
słowa kluczowego w JavaScript i jaka jest różnica między nimi
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żyjesz jednego z nich i dlaczego / co to robi?
Odpowiedzi:
Jeśli jesteś w zasięgu globalnym, nie ma dużej różnicy. Przeczytaj odpowiedź Kangaxa, aby uzyskać wyjaśnienie
Jeśli jesteś w funkcji, wówczas
var
utworzy zmienną lokalną, „no var” przeszuka łańcuch zasięgu, dopóki nie znajdzie zmiennej lub nie dotrze do zasięgu globalnego (w którym momencie ją utworzy):Jeśli nie wykonujesz zadania, musisz użyć
var
:źródło
Jest różnica .
var x = 1
deklaruje zmiennąx
w bieżącym zakresie (inaczej kontekst wykonania). Jeśli deklaracja pojawia się w funkcji - deklarowana jest zmienna lokalna; jeśli ma zasięg globalny - deklarowana jest zmienna globalna.x = 1
z drugiej strony jest jedynie przeniesieniem własności. Najpierw próbuje rozwiązać problemx
z łańcuchem zakresu. Jeśli znajdzie go gdziekolwiek w tym łańcuchu zasięgu, wykonuje przypisanie; jeśli nie znajdziex
, tylko wtedy tworzyx
właściwość na obiekcie globalnym (który jest obiektem najwyższego poziomu w łańcuchu zasięgu).Zauważ, że nie deklaruje zmiennej globalnej, lecz tworzy właściwość globalną.
Różnica między nimi jest subtelna i może być myląca, chyba że zrozumiesz, że deklaracje zmiennych również tworzą właściwości (tylko na obiekcie zmiennym) i że każda właściwość w JavaScript (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 między
var x = 1
ix = 1
(gdy jest wykonywana w zasięgu globalnym) polega na tym, że pierwsza deklaracja - zmienna - tworzy właściwość DontDelete, a druga nie. W konsekwencji właściwość utworzona za pomocą tego niejawnego przypisania można następnie usunąć z obiektu globalnego, a poprzednia - ta utworzona za pomocą deklaracji zmiennej - nie może zostać usunięta.Ale to oczywiście tylko teoria, aw praktyce istnieją między nimi jeszcze więcej różnic , z powodu różnych błędów we wdrożeniach (takich jak te z IE).
Mam nadzieję, że to wszystko ma sens :)
[Aktualizacja 2010/12/16]
W ES5 (ECMAScript 5; ostatnio znormalizowana, 5. edycja języka) znajduje się tak zwany „tryb ścisły” - opcjonalny tryb językowy, który nieznacznie zmienia zachowanie niezadeklarowanych zadań. W trybie ścisłym przypisanie do niezadeklarowanego identyfikatora to ReferenceError . Uzasadnieniem tego było złapanie przypadkowych zleceń, zapobiegając tworzeniu niepożądanych globalnych właściwości. Niektóre z nowszych przeglądarek już zaczęły obsługiwać tryb ścisły. Zobacz na przykład moją tabelę zgodności .
źródło
delete
zhackować zmienną deklarowaną przez zmiennąeval
. Jeśli pamiętam dokładną sztuczkę, opublikuję ją tutaj.var someObject = {}
isomeObject.someProperty = 5
? CzysomeProperty
stałby się globalny, a obiekt, który jest własnością, pozostaje lokalny?false
) , możesz o tym przeczytać w odniesieniu doObject.defineProperty
iObject.getOwnPropertyDescriptor
Mówienie, że różnica między „ lokalnym a globalnym ” nie jest do końca dokładne.
Lepiej byłoby myśleć o tym jak 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.
źródło
outer
nie jest zdefiniowanyvar global = false;
?var global = local;
w którym to przypadku bliski zasięg local byłby „lokalnym” zasięgiem zewnętrznym, który jest aktywnie definiowany. Choć dziwne staje się, gdybyś zmienił tę samą linię na,var global = global
w którym to przypadku najbliższy zakres podczas szukania wartościglobal
byłby wyższy o poziom w zakresie globalnego okna.Kiedy JavaScript jest wykonywany w przeglądarce, cały kod jest otoczony instrukcją with, na przykład:
Więcej informacji na temat
with
- MDNPonieważ
var
deklaruje zmienną w bieżącym zakresie , nie ma różnicy między zadeklarowaniemvar
w oknie a jej całkowitym zadeklarowaniem.Różnica pojawia się, gdy nie jesteś bezpośrednio w oknie, np. W funkcji lub w bloku.
Użycie
var
pozwala ukryć zmienne zewnętrzne o tej samej nazwie. W ten sposób możesz symulować zmienną „prywatną”, ale to już inny temat.Zasadą jest, aby zawsze używać
var
, ponieważ w przeciwnym razie istnieje ryzyko wprowadzenia subtelnych błędów.EDYCJA: Po otrzymaniu krytyki chciałbym podkreślić następujące kwestie:
var
deklaruje zmienną w bieżącym zakresiewindow
var
niejawnie deklarujevar
w zakresie globalnym (okno)var
jest tym samym, co pominięcie jej.var
nie jest tym samym, co zadeklarowanie zmiennej bezvar
var
wyraźnie, ponieważ jest to dobra praktykaźródło
let
w ES6.Zawsze używaj
var
słowa kluczowego do deklarowania zmiennych. Dlaczego? Dobra praktyka kodowania powinna być wystarczającym powodem sama w sobie, ale jej pominięcie oznacza, że jest zadeklarowana w zasięgu globalnym (taka zmienna nazywana jest „domniemanym” globalnym). Douglas Crockford zaleca nigdy nie używać domyślnych globałów i zgodnie z wytycznymi Apple JavaScript Coding :źródło
good coding practice
jest to zawsze wystarczający powód, jeśli jest to zalecana najlepsza praktyka, którą to jest i przez kilku autorów Javascript.Oto całkiem dobry przykład, w jaki sposób można złapać się na tym, że nie deklarujemy zmiennych lokalnych za pomocą
var
:(
i
jest resetowany przy każdej iteracji pętli, ponieważ nie jest deklarowany lokalnie wfor
pętli, ale globalnie) ostatecznie skutkując nieskończoną pętląźródło
Powiedziałbym, że lepiej jest używać
var
w większości sytuacji.Zmienne lokalne są zawsze szybsze niż zmienne o zasięgu globalnym.
Jeśli nie użyjesz
var
do deklarowania zmiennej, będzie ona miała zasięg globalny.Aby uzyskać więcej informacji, możesz przeszukać „zakres łańcucha JavaScript” w Google.
źródło
Nie używaj
var
!var
był sposobem na deklarację zmiennej sprzed ES6. Jesteśmy teraz w przyszłości i powinieneś kodować jako taki.Użyj
const
ilet
const
należy stosować 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 powinnyconst
.let
należy stosować dla każdej zmiennej, która ma zostać przypisana ponownie. Obejmuje to wewnątrz pętli for. Jeśli kiedykolwiek piszeszvarName =
poza inicjalizacją, użyjlet
.Oba mają zakres blokowy, zgodnie z oczekiwaniami w większości innych języków.
źródło
inna różnica np
podczas
źródło
var
?var a
jest podnoszony na szczyt zakresu i ustawiany na null, który deklaruje, ale nie inicjuje zmiennej, następnie w przypisaniu masz odwołanie do niezdefiniowanej zmiennej null, która zwraca wartość false, i ustaw przypisanie na[]
. W tym drugim przypadku masz przypisanie do właściwościa
nieruchomościa
. Możesz przypisać do właściwości, która nie istnieje - tworząc ją przy przypisaniu, ale nie możesz czytać z właściwości, która nie istnieje bezReferenceError
rzucenia się na ciebie.Używanie
var
jest zawsze dobrym pomysłem, aby zapobiec zaśmiecaniu zmiennych globalnego zasięgu, a konfliktom zmiennych powodując niechciane nadpisywanie.źródło
Bez
var
- zmienna globalna.Zdecydowanie zalecane ZAWSZE używaj
var
instrukcji, ponieważ globalna zmienna init w kontekście lokalnym - jest zła. Ale jeśli potrzebujesz tej brudnej sztuczki, powinieneś napisać komentarz na początku strony:źródło
Oto przykładowy kod, który napisałem, aby zrozumieć tę koncepcję:
źródło
@Chris S podał ładny przykład pokazujący praktyczną różnicę (i niebezpieczeństwo) pomiędzy
var
i nievar
. Oto kolejny, uważam, że ten jest szczególnie niebezpieczny, ponieważ różnica jest widoczna tylko w środowisku asynchronicznym, dzięki czemu można go łatwo wymknąć podczas testowania.Jak można oczekiwać, następujące dane wyjściowe fragmentu
["text"]
:Podobnie działa następujący fragment kodu (zwróć uwagę na brakujący
let
wcześniejarray
):Asynchroniczne wykonywanie manipulacji danymi nadal daje ten sam wynik za pomocą jednego modułu wykonującego:
Ale zachowuje się inaczej z wieloma:
Używając let:
źródło
Jako ktoś, kto próbuje się tego nauczyć, właśnie tak to widzę. Powyższe przykłady były dla początkujących nieco skomplikowane.
Jeśli uruchomisz ten kod:
Dane wyjściowe będą czytane jako: false, false, true, true
Ponieważ postrzega zmienne w funkcji jako oddzielne od zmiennych spoza niej, stąd termin zmienna lokalna, a to dlatego, że użyliśmy zmiennej var w przypisaniu. Jeśli usuniesz zmienną var w funkcji, która teraz brzmi następująco:
Dane wyjściowe to false, false, false, false
Wynika to z faktu, że zamiast tworzyć nową zmienną w lokalnym zasięgu lub funkcji, po prostu używa zmiennych globalnych i ponownie przypisuje je do wartości false.
źródło
Widzę, że ludzie są zdezorientowani, kiedy deklarują zmienne z lub bez var i wewnątrz lub na zewnątrz funkcji. Oto głęboki przykład, który przeprowadzi Cię przez następujące kroki:
Zobacz poniższy skrypt w akcji tutaj w jsfiddle
źródło
Wewnątrz kodu, jeśli używasz zmiennej bez użycia var, wtedy automatycznie dzieje się, że var var_name jest umieszczane w zasięgu globalnym, np .:
źródło
Oprócz kwestii zakresów, niektórzy wspominają również o podnoszeniu , ale nikt nie podał przykładu. Oto globalny zasięg:
źródło
Bez użycia zmiennych „var” można zdefiniować tylko po ustawieniu wartości. W przykładzie:
nie może działać w zasięgu globalnym ani żadnym innym zakresie . Powinien mieć wartość taką jak:
Z drugiej strony możesz zdefiniować wartościowe polubienie;
Jego wartość to
undefined
(Jego wartość nie jestnull
i nie jest równanull
interesująco.).źródło
my_var;
jest właściwie prawidłową instrukcją wyrażenia.my_var;
jest prawidłową instrukcją wyrażenia ./my_var;
byłoby niepoprawnym stwierdzeniem. Ale jak powiedziałem, to kazuistyka gramatyczna, przepraszam, mój komentarz był właściwie niewłaściwy.Powinieneś używać słowa kluczowego var, chyba że zamierzasz dołączyć zmienną do obiektu okna w przeglądarce. Oto link, który wyjaśnia zakres i różnicę między zasięgiem glocal a skalowaniem lokalnym za pomocą słowa kluczowego i bez słowa kluczowego var.
Kiedy zmienne są definiowane bez użycia słowa kluczowego var, to wygląda 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. Gdy interpreter wykonuje
dummyVariable = 20
, szuka deklaracji dummyVariable na początku funkcji. (Ponieważ wszystkie deklaracje zmiennych są przenoszone na początek kontekstu przez interpreter javascript, co nazywa się podnoszeniem)Możesz także spojrzeć na podnoszenie w javascript
źródło