Czy jest jakiś powód, aby używać słowa kluczowego „var” w ES6?

260

Przewodnik Babela po ES6 mówi:

letjest nowy var.

Najwyraźniej jedyna różnica polega na tym, że varzakres obejmuje bieżącą funkcję , a letzakres - bieżący blok . Istnieje kilka dobrych przykładów w tej odpowiedzi .

Nie widzę powodu, by używać varkodu ES6. Nawet jeśli chcesz objąć daną zmienną całą funkcję, możesz to zrobić, letumieszczając deklarację na górze bloku funkcyjnego, co i tak powinieneś zrobić, varaby wskazać rzeczywisty zakres. A jeśli chcesz dokładniej forokreślić zakres w bloku lub czymś innym , możesz to zrobić.

Więc mój instynkt polega na tym, żeby przestać varcałkowicie używać podczas pisania kodu ES6.

Moje pytanie brzmi: czy się mylę? Czy jest jakiś uzasadniony przypadek, w którym varbyłoby lepiej niż let?

kalus
źródło
3
Nie próbowałem tego jeszcze (ponieważ nie piszę jeszcze kodu ES6), ale wydaje się, że użycie varjako świadomego wskaźnika, że ​​zmienna ta ma być objęta zakresem całej funkcji, może być przydatną konwencją „samok dokumentującą” .
jfriend00
10
Jeśli umieścisz letinstrukcję bezpośrednio u góry funkcji, myślę, że to równie oczywiste, że zamierzałeś objąć ją całą funkcją. Nie sądzę, że używanie varczyni to bardziej zrozumiałym niż po prostu umieszczenie go na górze.
callum
11
Szczerze mówiąc, uważam, że jedynym powodem, dla którego varnadal istnieje, jest zgodność wsteczna. Gdyby tak nie było, varcałkowicie by usunęli lub nigdy nie przedstawili letsię, zamiast tego zmieniając semantykę na varto, co prawdopodobnie powinno być od samego początku.
Jörg W Mittag,
2
@RayToal Zgadzam się z 97% tego, co mówi Kyle Simpson, ale jego powody, dla których wciąż go używam, varwydają mi się cienkie i niewystarczające, aby uzasadnić posiadanie trzeciego rodzaju zmiennej, która skacze. Możesz zawęzić zakres letdo całej funkcji, po prostu umieszczając ją na górze funkcji, co jest o wiele wyraźniejsze w zamiarze niż pisanie varw bloku (aby wyciągnąć go z tego bloku, abyś mógł następnie użyć go poza blokiem - dziwne). Ostrzega, że ​​jeśli wybierzesz letfunkcję, to „to tylko pozycja, która sygnalizuje różnicę, a nie składnia”, ale myślę, że to dobrze.
callum
2
@RayToal Ja też przeczytałem ten artykuł (tuż przed przeczytaniem tej dyskusji) i byłem naprawdę rozczarowany jego bardzo słabym argumentem var. przykłady, które przedstawia dla zachowania, varwydają się wymyślone - i są oparte na poważnych błędach kodowania. O wiele lepiej jest popaść w błąd i zostać zmuszonym do naprawienia takich błędów, niż do korzystania z funkcji językowych, które pozwalają na to! Co dalej, radzimy zawinąć wszystko w try / catch, aby zapobiec awariom? Reszta tego linku jest dobra, ale w ogóle nie zgadzam się z tą konkretną częścią.
Mörre

Odpowiedzi:

217

Doug Crockford omawia letw tym momencie swojego wystąpienia „ The Better Parts ”.

Chodzi o to, że letunika źródła nieporozumień, szczególnie. dla programistów z oczekiwaniami określonymi przez języki z zakresem blokowym. varMa zakres funkcji (deklaruje zmienną, która jest widoczna w całej funkcji), mimo że wygląda jak to ma blokować zakresu .

var być może nadal będzie przydatny w ekstremalnym przypadku, takim jak kod generowany maszynowo, ale mocno się tam rozciągam.

( constjest również nowy i ma zakres blokowania. Po let x = {'hi': 'SE'}ponownym przypisaniu do x, a po const y = xtym , gdy nie możesz ponownie przypisać do y. Często jest to preferowane, ponieważ zapobiega przypadkowej zmianie się pod tobą. Ale dla jasności możesz nadal modyfikować obiekt, y.hi = 'SO'chyba że zamrozić.)

Realistycznie Twoje wrażenie jest właściwe dla ES6: Adopt leti const. Przestań używać var.

(W innym wykonaniu „Lepszych części” Doug mówi, dlaczego ===dodano, zamiast naprawiać problemy z== . ==Daje pewne „zaskakujące” wyniki, więc po prostu przyjmij ===.)


Przykład ujawnienia

Mozilla Developer Network podaje przykład, w którym varnie działa zgodnie z przeznaczeniem. Ich przykład jest realistyczny, który ustawia onclickprogramy obsługi na stronie internetowej. Oto mniejszy przypadek testowy:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

varzawodzi nas, ponieważ wszystkie iteracje pętli dzielą tę samą izmienną o zakresie funkcji , która ma wartość 5po zakończeniu pętli.

Jerry101
źródło
6
Podaje tę samą odpowiedź na temat adopcji === zamiast ==. Ten drugi jest zepsuty, ale komitet normalizacyjny ES nie chciał go zmienić, więc dodali === Nie jestem pewien, co to znaczy. ==wcale nie jest zepsuty. Można to po prostu zdefiniować jako equality comparison using coersionSprawdź na github.com/getify/You-Dont-Know-JS/blob/master/…
AmmarCSE
13
@AmmarCSE to wspaniały 39-stronicowy dokument na temat ukrytych przymusów. Kto może mieć to wszystko na uwadze podczas programowania? Doug miał na myśli „zepsuty”, jak podsumowano w stackoverflow.com/a/359509/1682419 , krótko mówiąc, łatwy do zdobycia, gdy typy wartości różnią się bardziej, niż zakładaliśmy. Czy potrafisz to wszystko przewidzieć? [ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101
2
tak, większość z tych przykładów dotyczy operandu tablicowego. Łatwo jest zrozumieć wynik, patrząc na toString i sposób jego implementacji dla obiektów . Jeśli jednak to właśnie rozumie słowo „ zepsuty”, to całkowicie rozumiem, skąd to się bierze. :-)
AmmarCSE
3
dlaczego nie użyć const, gdy nie jest to zmienne - po prostu pytasz? Chodzi mi o to, że prawdziwy wybór nie jest pomiędzy, leta varraczej pomiędzy let, varaconst
shabunc
4
vardziała zgodnie z planem, ale nie tyle osób się spodziewa. To błąd użyteczności, a nie błąd implementacji.
Jerry101
12

Jeśli piszesz poprawny kod, prawdopodobnie będziesz w stanie przekształcić wszystkie varinstrukcje w letinstrukcje bez żadnych zmian semantycznych.

letjest preferowane, ponieważ zmniejsza zakres, w którym widoczny jest identyfikator. Pozwala nam to bezpiecznie deklarować zmienne w miejscu pierwszego użycia.

constjest lepszy niż let. O ile nie musisz mutować odwołania, użyj constdeklaracji. Ma to wszystkie zalety związane letze zmniejszaniem obecności zmiennych zunifikowanych i ułatwianiem generowania kodu. Jeśli nie masz pewności, czy będziesz musiał zmutować odwołanie, zadeklaruj je, constdopóki wyraźnie nie będziesz musiał tego zrobić.

Aluan Haddad
źródło
5

Niekoniecznie uważam, że się mylisz, ale istnieją pewne zastrzeżenia dotyczące używania var. Zasadniczo letpowinien pomóc programistom obejść głupotę JavaScript, szczególnie w przypadku konfliktów nazw. var, wydaje się, że ma większy zasięg, ponieważ chce przejść do zakresu funkcji zamykania. Będą chwile, kiedy będziesz potrzebować var, na przykład gdy potrzebujesz zmiennej temp, która będzie dostępna w zakresie bloku wewnątrz funkcji, w przeciwnym razie, preferowanie zamiast letvar pomoże programistom w konfliktach nazw. Mówiąc prościej, najwyższy czas wprowadzić ES6 let.

ciekawy
źródło
3
Temperatura varw bloku jest dostępna w obrębie całej funkcji, a nie w zakresie bloków. To wprowadzająca w błąd funkcja.
Jerry101
1

Zgadzam się, że w es6 powinno się używać tylko „let”. AFIK, ponowne napisanie „let” generuje błąd (co jest dobre), natomiast w „var” po prostu nadpisujesz wartość (choć „tryb ścisły” w es5 też się tym zajmuje).

yar1
źródło
-4

letoznacza „niech zmienna będzie równa”. Innymi słowy, jest to deklaracja, inicjalizacja i zadanie.

Istnieje w przeciwieństwie do tego, constco oczywiście oznacza „stały” - co jest przeciwieństwem zmiennej.

Niektóre inne języki używają przedrostka rzeczywistego obiektu zamiast obiektu podczas deklarowania go (np. defJest skrótem dla „funkcji definiującej” - całkowicie pomijając sens tego, co jest „def”.

Let dodaje tę semantyczną niespójność do Javascript.

Logicznie można pozwolić, aby stała była równa coś, ponieważ zadaniem słowa kluczowego „let” jest przypisanie pamięci.

Problem powstaje, ponieważ varsłowo kluczowe zostało wprowadzone wcześniej, ponieważ constbyło obsługiwane, więc zgodność wsteczna dyktuje, że varnie musi to oznaczać zmiennej. (Można go również użyć do przypisania stałej wartości.)

Stąd wprowadzenie letw złej pozycji. Aby upewnić się, że pamiętamy, że leksykalnie, to jest złe, postanowili również zmienić zakres leksykalny letvs var, więc niespójność jest przede wszystkim w naszych umysłach podczas debugowania.

Innymi słowy, letistnieje, ponieważ ludzie (czyli opiekunowie języków) uważali, że JavaScript jest zbyt spójny, po opanowaniu wszystkich jego idiomów i osobliwości pragną więcej.

Uwaga dodatkowa, varnie działa w blokach „strzałkowych”, jeśli chcesz traktować te bloki jako zamknięcia (ponieważ varwprowadzono je przed traktowaniem bloków jako zamknięcia), ale letdziała.

fijiaaron
źródło
6
-1: pedantyczny, nieprzydatny, a przede wszystkim oparty na opiniach.
Joel Mueller
Fijiaaron tylko tutaj żartuje.
Jerry101
Popieram twoją niechęć do formy leksykalnej, letponieważ jest ona sprzeczna z tonem innych słów kluczowych w tej samej kategorii w JavaScript. To jednak nie odpowiada na pytanie i nie jest szczególnie dobrze postawione. Przesłuchany
Aluan Haddad,
3
letto nie tylko programiści pragnący większej złożoności. Jest to w rzeczywistości bardziej intuicyjnie zrozumiałe, ponieważ kiedy zapętlasz i zamykasz przez zmienne, zamknięcie zachowuje ostatnią wartość var, ale kiedy robisz to samo w przypadku let, każde zamknięcie w pętli ma własną wartość dla let, a la przykład @ Jerry101 powyżej
TKoL