Ile powinienem używać „let” vs „const” w ES6?

214

Ostatnio pisałem dużo kodu ES6 dla io.js. Na wolności nie ma zbyt wiele kodu do nauki, więc czuję, że definiuję własne konwencje.

Moje pytanie brzmi, kiedy w użyciu constvs let.

Stosowałem tę zasadę: Jeśli to możliwe, użyj const. Używaj tylko, letjeśli wiesz, że jego wartość musi się zmienić. (Zawsze możesz wrócić i zmienić a constna a, letjeśli później okaże się, że musisz zmienić jego wartość).

Głównym powodem tej reguły jest to, że łatwo ją konsekwentnie stosować. Nie ma szarych obszarów.

Chodzi o to, że kiedy stosuję tę zasadę, w praktyce 95% moich deklaracji to const. I to wydaje mi się dziwne. Jestem tylko przy użyciu letrzeczy jak iw forpętli, lub od czasu do czasu na takie rzeczy jak skumulowane sumy Fibonacciego (który nie pojawia się wiele w życiu). Zaskoczyło mnie to - okazuje się, że 95% „zmiennych” w moim kodzie ES5 do tej pory dotyczyło wartości, które się nie zmieniają. Ale widzenie constcałego mojego kodu wydaje się jakoś źle.

Moje pytanie brzmi: czy można consttak często korzystać? Czy naprawdę powinienem robić takie rzeczy const foo = function () {...};?

A może powinienem zarezerwować constna takie sytuacje, w których kodujesz literał na samym szczycie modułu - na przykład w przypadku wielkich liter const MARGIN_WIDTH = 410;?

kalus
źródło
7
Podejrzewam, że to pytanie jest oparte głównie na opiniach i dlatego prawdopodobnie zostanie zamknięte, ale moje 2 centy: Używanie consttego jest w porządku .
jhominal
15
function foo() {...}jest lepszy niż<anything> foo = function() {...}
OrangeDog,
12
@OrangeDog Chciałbym zobaczyć twoje wyjaśnienie, ponieważ doszedłem do dokładnie przeciwnego zdania. Jest zastrzeżenie, które function foo() {...}może powodować niewielkie zamieszanie podczas debugowania z powodu podnoszenia. Ponadto jego istnienie oznacza, że ​​mamy dwie konstrukcje, które robią to samo, ale jedna z nich działa tylko w bardzo specyficznym kontekście. (Możesz użyć wyrażenia funkcyjnego wszędzie tam, gdzie istnieje wyrażenie, ale możesz użyć deklaracji funkcji tylko na poziomie instrukcji.) Jeśli wolisz zwięzłość, problemem może być to, że składnia wyrażenia funkcyjnego używa całego słowa function.
Keen
11
Ślady stosu mają nazwę funkcji zamiast anonu. Podnoszenie jest dobre i pozwala ci definiować funkcje w naturalnej kolejności, bez konieczności martwienia się o niezdefiniowanie foo.
OrangeDog,
1
Są to dobre punkty, o których warto pamiętać, ale nie jestem jeszcze przekonany. Nowoczesne debuggery wykonują dobrą robotę, wybierając odpowiednią nazwę wyświetlaną dla funkcji na podstawie tego, do którego symbolu ją przypisujesz (jeśli w ogóle - jeśli nie, możesz użyć nazwanego wyrażenia funkcji). Deklaracja naturalnej kolejności funkcji jest wysoce subiektywna. Rozsądne może być myślenie, że naturalnym porządkiem jest rozpoczęcie od zdefiniowania podstawowych elementów, a następnie zdefiniowanie elementów, które ich używają.
Keen

Odpowiedzi:

183

Moja odpowiedź tutaj nie jest związana z javascript.

Jako ogólną zasadę w każdym języku, który pozwala mi to zrobić w pół-łatwy sposób, powiedziałbym, że zawsze używaj const / final / readonly / cokolwiek to się nazywa w twoim języku, kiedy tylko jest to możliwe. Powód jest prosty, o wiele łatwiej jest wnioskować o kodzie, gdy nie wiadomo, co można zmienić, a co nie. Oprócz tego w wielu językach można uzyskać pomoc techniczną, która mówi, że robisz coś złego, gdy przypadkowo przypisujesz zmienną, którą zadeklarowałeś jako const.

Cofanie się i zmiana stałej na let jest bardzo proste. A przejście do trybu domyślnego powoduje, że musisz się dwa razy zastanowić. I w wielu przypadkach jest to dobra rzecz.

Ile widziałeś błędów, które powodowały nieoczekiwane zmiany zmiennych? Chyba dużo. Wiem, że większość błędów, które widzę, obejmują nieoczekiwane zmiany stanu. Nie pozbędziesz się tych wszystkich błędów, swobodnie używając const, ale pozbędziesz się ich wszystkich!

Ponadto wiele języków funkcjonalnych ma niezmienne zmienne, w których wszystkie zmienne są domyślnie stałe. Spójrz na przykład na Erlang lub F #. Kodowanie bez przypisania działa idealnie w tych językach i jest jednym z wielu powodów, dla których ludzie kochają programowanie funkcjonalne. Z tych języków można się wiele nauczyć na temat zarządzania stanem, aby zostać lepszym programistą.

A wszystko zaczyna się od bycia wyjątkowo liberalnym z Const! ;) To tylko dwa znaki do napisania w porównaniu do let, więc śmiało i tak dalej const!

wasatz
źródło
45
constto dwie kolejne postacie niż let...
OrangeDog,
72
Ale 5 znaków mniej niż niezmienne.
Cerad,
7
Wydaje się to bardzo podobne do używania valw Scali (która deklaruje zmienną jako niezmienną) i używania var(mutable odpowiednika) tylko wtedy, gdy nie możemy użyć val. Innymi słowy, deklarujemy zmienne jako domyślnie niezmienne i wprowadzamy zmienność tylko wtedy, gdy jest to absolutnie potrzebne (co może być po prostu spowodowane tym, że zmienne podejście jest czystsze).
Kat
7
Zgadzam się z tą odpowiedzią, ale pamiętam, że rzeczy nie są tak oczywiste podczas pracy z rzeczami takimi jak zwykłe obiekty lub tablice, ponieważ ich właściwości mogą się zmieniać, nawet jeśli zostały zdefiniowane za pomocą „const”. Myślałem o tym, że „const” działa jak object.freeze, ale tak nie jest.
backdesk
2
@Cerad Miałeś na myśli „4 znaki mniej” czy brakuje mi tutaj jakiegoś żartu?
Mathias Bynens,
57

Uważaj, ponieważ constklucze obiektów można modyfikować.

Stąd: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

klucze obiektów nie są chronione

rozważ ten przykład:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

To samo dotyczy tablic:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

Nie zdecydowałem się całkowicie sam, ale rozważam użycie constwszystkich obiektów nie-tablicowych / innych niż obiektowe i użycia letdla obiektów / tablic.

lax4mike
źródło
34
To prawda, ale oczekiwane IMO - stałe jest odniesienie do obiektu przypisane do twojego const. colors = numbersnie będzie działać zgodnie z oczekiwaniami. Jeśli chcesz chronić swoje właściwości obiektu, możesz użyć Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Josef Engelfrost
16
Zwodniczy. Jest niezmienny. Ale rzeczywiste właściwości obiektu nie są.
Gaston Sanchez,
1
+1 Tak, referencja jest chroniona, ale jeśli chodzi o pytanie , używanie jej w takich przypadkach jest dość głupie const moment = require('moment'), chyba że jesteś osobą, która martwi się, że ktoś spróbuje to zrobić moment = dead.fish(() => pizza)później.
MaxWell,
5
Być może bardziej realistyczne moment = Date.now(). Ale w każdym razie, jeśli kod zakłada niezmiennik, nie widzę nic złego w egzekwowaniu go w miarę możliwości.
James M.
3
Nikt jednak nie powiedział, że nie są niezmienni. Powszechnym nieporozumieniem jest to, że celem const jest uczynienie go niezmiennym, gdy naprawdę ma zagwarantować, że nazwa nigdy nie będzie odwoływać się do innego obiektu niż ten, dla którego została zainicjowana.
monokrom
25

Nie martw się o to. constjest niesamowitym dodatkiem do JavaScript i polecam używać go we wszystkich miejscach, które ma sens. To sprawia, że ​​kod jest bardziej niezawodny.

Jeśli chodzi o obiekty, constbędzie chronić twoją zmienną przed ponownym przypisaniem, ale jeśli potrzebujesz niezmiennych obiektów, będziesz potrzebować Object.freezemetody, patrz poniżej.

const immutableOject = Object.freeze({immutableProperty: 'foo'});

constochroni tylko przed ponownym przypisaniem, a freezemetoda ochroni wszystkie bezpośrednie właściwości. Jeśli wszystkie zagnieżdżone właściwości również są niezmienne, musisz freezeje rekurencyjnie .

clean_coding
źródło
14
Zauważ, że Object.freezejest płytki.
Mathias Bynens,
@MathiasBynens Natknąłem się na ten komentarz i jestem ciekaw, co dokładnie miałeś na myśli. Czy mógłbyś proszę opracować?
Cole Roberts,
@ColeRoberts Pojęcie płytkiej niezmienności ma miejsce wtedy, gdy odwołanie do obiektu jest niezmienne, ale właściwości można nadal zmieniać. Słowo kluczowe const powoduje płytką niezmienność, dlatego musisz użyć Object.freeze, jeśli wszystkie właściwości również są niezmienne.
clean_coding
3
@ColeRoberts Oznacza, że ​​wartości obiektów w zamrożonym obiekcie (tj. Obiekty zagnieżdżone) można nadal mutować. Więcej informacji można znaleźć na stronie mathiasbynens.be/notes/es6-const#immutable-values .
Mathias Bynens,
19

W moim ES6 constnie chodzi o post niezmienności , wyjaśniam, co constdokładnie znaczy zgodnie ze specyfikacją.

W oparciu o te obiektywne fakty, oto moje osobiste preferencje:

[…] Ma sens użycie leti constw następujący sposób w kodzie ES6:

  • użyj constdomyślnie
  • używaj tylko letwtedy, gdy konieczne jest ponowne wiązanie (tj. dowolna zmiana przypisania)
  • ( varnie należy używać w ES6)

Może to być subiektywne, ale faktem jest, że to najbardziej pasuje do intencji specyfikacji.

Ludzie, którzy używają letdomyślnie zwykle traktują constzmienne jako stałe (które niekoniecznie są z założenia!). Dla każdego z nich, ale wolę używać rzeczy zgodnie z ich przeznaczeniem, a nie dla niektórych wymyślonych znaczeń, które ludzie przypisują temu na podstawie nieporozumienia.

Używanie consttylko do stałych jest jak używanie elementu HTML<aside> tylko do zawartości paska bocznego.

Mathias Bynens
źródło
2
Dlaczego nazwałbyś coś, constjeśli nie jest stałe?
nu everest
3
@nueverest Ponieważ nie po to constjest. Czy przeczytałeś powyższe?
Mathias Bynens,
2
@MathiasBynens Myślę, że (jedynym?) Problemem constjest to, że się nazywa const. To głupie imię (w javascript), które na początku dezorientuje wielu (wszystkich?) Programistów. IMO lepiej byłoby, gdyby constzostał powołany let(zwłaszcza dlatego, że letjest krótszy, ale constjest znacznie bardziej powszechny) i letnazwany czymś innym.
MrN00b
@MathiasBynens Rozumiem, ale dlaczego tak to nazywać? Powoduje to ogromne zamieszanie, jak pokazuje ta strona.
jtr13
4

Moje osobiste podejście, pomyślane o pomocy w czytaniu i zrozumieniu kodu:


letjest tylko dla zmiennych krótkotrwałych, zdefiniowanych w jednym wierszu i nie zmienianych później. Zasadniczo te zmienne, które są tylko po to, by zmniejszyć ilość pisania. Na przykład:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

constdla wszystkich nazw znanych jako stałe w całym module. Bez uwzględnienia lokalnych wartości stałych. Na valueprzykład powyższy przykład ma stały zasięg i może być zadeklarowany za pomocą const, ale ponieważ istnieje wiele iteracji i dla każdej z nich istnieje wartość o tej samej nazwie „wartość”, która może skłonić czytelnika do myślenia, że valuezawsze jest to samo. Moduły i funkcje są najlepszym przykładem constzmiennych:

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

varza wszystko, co może być zmienne. Nazwy, które mogą mylić osoby czytające kod, nawet jeśli są stałe lokalnie i nie są odpowiednie let(tj. Nie są wypełnione w prostej deklaracji bezpośredniej), ubiegają się o deklarację za pomocą var. Na przykład:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

Dalsze komentarze i możliwe przyszłe aktualizacje tutaj .

Fiatjaf
źródło
10
ten drugi fragment kodu wygląda jak broń.
Julian
1

JavaScript jest trochę wyjątkowy, ponieważ zmienne mogą być funkcjami i takimi, ale weź pod uwagę C #, Java lub inny podobny język w stylu C:

const public void DoSomething()

Jest constto dziwne, a to dlatego, że deklaracje metod w tych językach nie mogą się zmienić, gdy zostaną one skompilowane w coś innego, to jest to, co robią, bez względu na wszystko (ignorując niektóre okropne hacki, które mogą istnieć).

Dlaczego JavaScript powinien być inny? Więc nie jest skompilowany, ale to nie znaczy, że powinniśmy porzucić bezpieczeństwo, które kompilatory mogą zapewnić. Użycie constsłowa kluczowego zapewnia nam większe bezpieczeństwo, co z pewnością doprowadzi do bardziej niezawodnych aplikacji.

Joe
źródło