Stała w JavaScript: kiedy go używać i czy jest to konieczne?

349

Ostatnio natrafiłem na constsłowo kluczowe w JavaScript. Z tego, co mogę powiedzieć, jest on używany do tworzenia niezmiennych zmiennych , i przetestowałem, aby upewnić się, że nie można go przedefiniować (w Node.js):

const x = 'const';
const x = 'not-const';

// Will give an error: 'constant 'x' has already been defined'

Zdaję sobie sprawę, że nie jest on jeszcze ustandaryzowany we wszystkich przeglądarkach - ale interesuje mnie tylko kontekst Node.js V8 , i zauważyłem, że niektórzy programiści / projekty wydają się faworyzować go, gdy varsłowo kluczowe może być użyte do ten sam efekt.

Więc moje pytania to:

  • Kiedy należy używać constzamiast var?
  • Czy należy go używać za każdym razem, gdy deklarowana jest zmienna, która nie będzie ponownie przypisywana?
  • Czy faktycznie robi to różnicę, jeśli varjest stosowany zamiast constlub odwrotnie?
axdg
źródło
1
Nie wydaje się to jeszcze być ustandaryzowane (może w EC6?). Dodatkowe informacje na ten temat znajdziesz tutaj: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Sebastien C.
1
Const ma słabą
Deepu

Odpowiedzi:

462

Pytania mają dwa aspekty: jakie są techniczne aspekty korzystania constzamiast vari jakie są związane z tym ludzkie aspekty.

Różnica techniczna jest znacząca. W skompilowanych językach stała zostanie zastąpiona w czasie kompilacji, a jej użycie pozwoli na inne optymalizacje, takie jak usuwanie martwego kodu, w celu dalszego zwiększenia wydajności środowiska wykonawczego kodu. Najnowsze (luźno używane określenie) silniki JavaScript faktycznie kompilują kod JS, aby uzyskać lepszą wydajność, więc użycie słowa kluczowego const poinformuje ich, że opisane powyżej optymalizacje są możliwe i powinny zostać wykonane. Powoduje to lepszą wydajność.

Aspekt związany z człowiekiem dotyczy semantyki słowa kluczowego. Zmienna to struktura danych zawierająca informacje, które powinny ulec zmianie. Stała to struktura danych, która zawiera informacje, które nigdy się nie zmienią. Jeśli jest miejsce na błędy, varnależy zawsze używać. Jednak nie wszystkie informacje, które nigdy nie zmieniają się w czasie trwania programu, muszą zostać zadeklarowane za pomocą const. Jeśli w różnych okolicznościach informacje powinny ulec zmianie, użyj, varaby to zaznaczyć, nawet jeśli rzeczywista zmiana nie pojawia się w kodzie.

Tibos
źródło
4
Na zdrowie, założyłem, że Mozilla / Google nie dodałoby stałej obsługi silników JS bez powodu. W razie potrzeby zastosuję const.
axdg
6
constobiekty wydają się być zmienne, więc nie jestem pewien, jak bardzo kompilator JS jest naprawdę. Może tryb „użyj ścisłego” również robi różnicę.
Rudie
9
@ Rudie Funkcja, której szukasz, nazywa się zamrażaniem obiektu. constpo prostu zapobiega zmianie przypisania „zmiennej” do innej wartości. const a = {}; a = {};wyrzuci błąd w trybie ścisłym.
Tibos,
Generalnie używam const zamiast let dla większości zmiennych, tak jak w Javie dodaję finał do większości deklaracji zmiennych.
kodowanie
2
If there is room for error, var should always be used. Dziś nie ma to już zastosowania, a narzędzia takie jak ESLint natychmiast wskazują na constnaruszenie.
vitaly-t
72

Aktualizacja 2017

Ta odpowiedź wciąż cieszy się dużym zainteresowaniem. Warto zauważyć, że ta odpowiedź została opublikowana na początku 2014 roku i od tego czasu wiele się zmieniło.wsparcie jest teraz normą. Wszystkie nowoczesne przeglądarki obsługują teraz, constwięc korzystanie z niego powinno być całkiem bezpieczne bez żadnych problemów.


Oryginalna odpowiedź z 2014 roku

Pomimo dość przyzwoitej obsługi przeglądarki , na razie unikałbym jej używania. Z artykułu MDN na tematconst :

Obecna implementacja const jest rozszerzeniem specyficznym dla Mozilli i nie jest częścią ECMAScript 5. Jest obsługiwana w Firefox i Chrome (V8). Począwszy od Safari 5.1.7 i Opera 12.00, jeśli zdefiniujesz zmienną ze stałą w tych przeglądarkach, możesz nadal zmienić jej wartość później. Nie jest obsługiwany w Internet Explorerze 6-10, ale jest zawarty w Internet Explorerze 11. Słowo kluczowe const obecnie deklaruje stałą w zakresie funkcji (podobnie jak zmienne zadeklarowane przez var).

Następnie mówi:

constzostanie zdefiniowany przez ECMAScript 6, ale z inną semantyką. Podobnie jak zmienne zadeklarowane za pomocą instrukcji let, stałe zadeklarowane za pomocą const będą mieć zasięg blokowy.

Jeśli używasz, constmusisz dodać obejście, aby obsługiwać nieco starsze przeglądarki.

James Donnelly
źródło
6
Świetna odpowiedź - chociaż już przeczytałem artykuł na temat MDN. Jak powiedziałem, byłem bardziej zainteresowany tym, czy V8 faktycznie będzie traktować const inaczej niż var. Myślę, że @ Tibos to wyjaśniło.
axdg
James dziękuje za zwrócenie uwagi na aspekt wsparcia. imho wszystkie odpowiedzi w javascript powinny zawierać podział na obsługę przeglądarki. ładnie wyjaśnione
hubson bropa,
4
Uwaga ES6 otrzymał zamrożenie funkcji w sierpniu 2014 r. W lipcu 2015 r. Standard został oficjalnie wydany. Jeśli czytasz to teraz, oznacza to, że powinieneś postępować zgodnie z zaakceptowaną odpowiedzią przedstawioną poniżej, jeśli kodem zarządza aktualny silnik.
Filip Dupanović
Pytanie OP jest specyficzne dla node.js
Nicu Surdu,
@NicolaeSurdu na pewno. Jest to również od stycznia 2014 r., Więc prawdopodobnie jest obecnie w większości zbędny w 2017 r.
James Donnelly,
41

Po co korzystać const, odpowiedź @ Tibos jest świetna.

Ale powiedziałeś:

Z tego, co mogę powiedzieć, służy do tworzenia niezmiennych zmiennych

Że jest źle . Mutowanie zmiennej różni się od zmiany przypisania:

var hello = 'world' // assigning
hello = 'bonjour!' // reassigning

Z const nie możesz tego zrobić:

const hello = 'world'
hello = 'bonjour!' // error

Ale możesz mutować swoją zmienną:

const marks = [92, 83]
marks.push(95)
console.log(marks) // [92, 83, 95] -> the variable has been mutated.

Tak więc każdy proces, który zmienia wartość zmiennej bez użycia =znaku, mutuje zmienną.

Uwaga: +=na przykład to ... ponowne przypisanie!

var a = 5
a += 2 // is the same as a = a + 2

Podsumowując: constnie przeszkadza ci mutować zmiennych, nie pozwala ci na ich ponowne przypisanie .

math2001
źródło
4
twoje stwierdzenie „jakikolwiek proces, który zmienia wartość zmiennej bez użycia =znaku wycisza się” jest technicznie niepoprawny. Na przykład const marks=[92,83]; marks[2]=95; console.log(marks)wyświetli [92, 83, 95]. markszostał zmutowany za pomocą znaku równości.
chharvey
5
„Ale powiedziałeś: << Z tego, co mogę powiedzieć, służy do tworzenia niezmiennych zmiennych >> To źle . Mutowanie zmiennej różni się od ponownego przypisywania.” Nie, nie jest. Ponowne przypisanie oznacza mutację zmiennej. Mówisz o mutowaniu obiektu, do którego odnosi się odwołanie w zmiennej. To zupełnie inna sprawa.
TJ Crowder
Dostałem się tutaj, ponieważ próbuję zrozumieć constw kontekście tablic (podobnie jak w przykładzie użytym @chharvey). W przypadku jest ponownie przypisane za każdym razem. Dlaczego więc korzystać, a nie ? const countArray = countup(n - 1); countArray.push(n);constconstvar
YCode
1
@YCode no. podczas używania const countArray, to będzie nigdy być przeniesiony. Nadal możesz przesuwać do tablicy, która zmienia jej elementy i długość, ale nie nazywamy tego ponownym przypisywaniem. używasz constzamiast letlub vargdy chcesz zapobiec zmianie przypisania. BTW, jeśli nie chcesz, aby realokacja, letjest prawie zawsze lepsze niż var.
chharvey
@chharvey Thanks! Twoja odpowiedź doprowadziła mnie do „przejścia przez wartość vs przekazanie przez odniesienie”, nowej koncepcji i dziwnej - gdzie zmiana wartości ≠ zmiana przypisania. Każdy, kto potrzebuje dalszych wyjaśnień, powinien sprawdzić odpowiedzi tutaj: stackoverflow.com/q/46131828/5965865
YCode
38

Aby zintegrować poprzednie odpowiedzi, istnieje oczywista zaleta w deklarowaniu zmiennych stałych, oprócz przyczyny wydajności: jeśli przypadkowo spróbujesz je zmienić lub ponownie zadeklarować w kodzie, program odpowiednio nie zmieni wartości ani nie zgłosi błędu.

Na przykład porównaj:

// Will output 'SECRET'

const x = 'SECRET'
if (x = 'ANOTHER_SECRET') {  // Warning! assigning a value variable in an if condition
    console.log (x)
}

z:

// Will output 'ANOTHER_SECRET'

var y = 'SECRET'
if (y = 'ANOTHER_SECRET') { 
    console.log (y)
}

lub

// Will throw TypeError: const 'x' has already been declared

const x = "SECRET"

/*  complex code */

var x = 0

z

// Will reassign y and cause trouble

var y = "SECRET"

/*  complex code */

var y = 0
konferencja janes
źródło
Powinieneś powiedzieć, że to „niezmienne” zachowanie dotyczy tylko ciągów znaków, typów podstawowych. Używając obiektów, tablic itp. Można zmienić wartości, ale nie można ponownie przypisać nowego „obiektu”, np. Const a = [„a”, „b”]; a = []; zwróci błąd, w przeciwnym razie jest to możliwe
Fer To
Powinieneś mieć przykład, w którym również próbujesz zmienić wartość stałej.
Joshua Pinter,
Używanie const jest bardzo podobne do modyfikatorów dostępu, prawdziwym niezmiennością nie jest cel.
StingyJack
32

constnie jest niezmienny.

Z MDN :

Deklaracja const tworzy odwołanie do wartości tylko do odczytu. Nie oznacza to, że wartość, którą posiada, jest niezmienna, po prostu nie można przypisać identyfikatora zmiennej.

Anthony
źródło
24
To trochę mylące. Liczby, łańcuchy, logiczne itp. (Prymitywy) constsą niezmienne. W przypadku obiektów i tablic nie można go ponownie przypisać, ale zawartość można zmienić (np. Array.push).
Florian Wendelborn,
2
Prymitywy JS są jednak zawsze niezmienne. To, czy używasz, constczy nie, nie ma na to wpływu.
maja 21
1
@Dodekeract dlatego nie jest niezmienne z definicji. Jeśli wartości mogą się zmienić, nie jest to niezmienne, chociaż działa jako niezmienne dla wymienionych tu prymitywów
Anthony
13

var : Deklaracja zmiennej, inicjalizacja wartości opcjonalna.

let : Deklaracja zmiennej lokalnej o zasięgu bloku.

const : Zadeklaruj stałą tylko do odczytu.

Dawny:

var a;
a = 1;
a = 2;//re-initialize possible
var a = 3;//re-declare
console.log(a);//3

let b;
b = 5;
b = 6;//re-initiliaze possible
// let b = 7; //re-declare not possible
console.log(b);

// const c;
// c = 9;   //initialization and declaration at same place
const c = 9;
// const c = 9;// re-declare and initialization is not possible
console.log(c);//9
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.
Srikrushna
źródło
10

Masz świetne odpowiedzi, ale bądźmy prostsze.

const powinien być używany, gdy masz zdefiniowaną stałą (czytaj jako: nie zmieni się podczas wykonywania programu).

Na przykład:

const pi = 3.1415926535

Jeśli uważasz, że jest to coś, co można zmienić w późniejszym wykonaniu, użyj var.

Różnica praktyczna, oparta na tym przykładzie, polega na tym, że przy założeniu, constże pi będzie wynosić 3,14 [...], to fakt.

Jeśli zdefiniujesz to jako var, może to być 3,14 [...] lub nie.

Aby uzyskać bardziej techniczną odpowiedź, @Tibos ma rację akademicką.

Edgar Griñant
źródło
7

Z mojego doświadczenia używam const, gdy chcę ustawić coś, co chciałbym zmienić później, bez konieczności przeszukiwania kodu w poszukiwaniu bitów, które zostały zakodowane na stałe, np. Ścieżka do pliku lub nazwa serwera.

Błąd w testowaniu to kolejna sprawa, próbujesz stworzyć inną zmienną o nazwie x, byłby to dokładniejszy test.

const x = 'const';
x = 'not-const';
Funkotron_King
źródło
9
Rozumiem, co masz na myśli, ale - to zabawne, że „stały” oznacza dla ciebie „rzecz, którą chciałbym zmienić”. : P
Venryx
4

Naprawdę osobiste preferencje. Możesz użyć const, gdy, jak mówisz, nie zostanie on ponownie przypisany i będzie stały. Na przykład, jeśli chcesz przypisać swoje urodziny. Twoje urodziny nigdy się nie zmieniają, więc możesz użyć go jako stałej. Ale twój wiek się zmienia, więc może to być zmienna.

Carl Markham
źródło
17
To byłby bardzo długi skrypt!
zerowanie
3
@nullability Zależy od tego, ile osób śledzisz. Kilkadziesiąt i skrypt nie będzie musiał długo działać :).
Millie Smith,
4

Podsumowanie:

const tworzy niezmienne wiązanie, co oznacza, że ​​identyfikator zmiennej const nie nadaje się do ponownego przypisania.

const a = "value1";

nie można go ponownie przypisać za pomocą

a = "value2";

Jeśli jednak identyfikator const zawiera obiekt lub tablicę, jego wartość można zmienić, o ile nie przypisujemy go ponownie.

const x = { a: 1 }

x.a = 2; //is possible and allowed

const numbers = [1, 2];
numbers.push(3); //is possible and allowed

Zauważ, że const ma zasięg blokowy, podobnie jak let, który nie jest taki sam jak var (który ma zasięg funkcjonalny)

W skrócie: Jeśli coś nie zmieni się w wyniku ponownego przypisania, użyj const lub użyj let lub var w zależności od zakresu, który chcesz mieć.

O wiele łatwiej jest uzasadnić kod, gdy nie wiadomo, co można zmienić poprzez zmianę przypisania, a co nie. Zmiana stałej na let jest bardzo prosta. A przejście do trybu domyślnego powoduje, że musisz się dwa razy zastanowić, zanim to zrobisz. I w wielu przypadkach jest to dobra rzecz.

Tejas Patel
źródło
2
Main point is that how to decide which one identifier should be used during development.
In java-script here are three identifiers.

1. var (Can re-declared & re-initialize)
2. const (Can't re-declared & re-initialize, can update array values by using push)
3. let (Can re-initialize but can't re-declare)

„var”: w momencie kodowania, kiedy mówimy o standardzie kodu, zwykle używamy nazwy identyfikatora, który jest łatwy do zrozumienia dla innych użytkowników / programistów. Na przykład, jeśli pracujemy, myśleliśmy o wielu funkcjach, w których wykorzystujemy dane wejściowe i przetwarzamy je i zwracamy pewne wyniki, takie jak:

**Example of variable use**

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2;
 return result;
}

W powyższych przykładach obie funkcje dają różne wyniki-2, ale używają tej samej nazwy zmiennych. Tutaj widzimy, że „proces” i „wynik” są używane jako zmienne i powinny być.

 **Example of constant with variable**

 const tax = 10; 
 const pi = 3.1415926535; 

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

Przed użyciem „let” w skrypcie java musimy dodać „use strict” na górze pliku js

 **Example of let with constant & variable**

 const tax = 10; 
 const pi = 3.1415926535; 
 let trackExecution = '';

function firstFunction(input1,input2)
{
 trackExecution += 'On firstFunction'; 
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 trackExecution += 'On otherFunction'; # can add current time 
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

 firstFunction();
 otherFunction();
 console.log(trackExecution);

W powyższym przykładzie możesz śledzić, która z funkcji została wykonana, a która nie była używana podczas określonej akcji.

vinod
źródło
1

Po pierwsze, trzy przydatne rzeczy const(oprócz ulepszeń zakresu, którymi się dzieli let):

  • Dokumentuje dla osób czytających kod później, że wartość nie może się zmienić.
  • Zapobiega to zmianie wartości przez Ciebie (lub kogokolwiek, kto przyjdzie za Tobą), chyba że cofnie się i celowo zmieni deklarację.
  • Może to zaoszczędzić silnikowi JavaScript trochę analizy pod kątem optymalizacji. Na przykład zadeklarowałeś, że wartość nie może się zmienić, więc silnik nie musi pracować, aby dowiedzieć się, czy wartość się zmienia, aby mógł zdecydować, czy przeprowadzić optymalizację na podstawie wartości, która się nie zmienia.

Twoje pytania:

Kiedy należy używać constzamiast var?

Możesz to zrobić za każdym razem, gdy deklarujesz zmienną, której wartość nigdy się nie zmienia. To, czy uznasz to za właściwe, zależy wyłącznie od twoich preferencji / preferencji twojego zespołu.

Czy należy go używać za każdym razem, gdy deklarowana jest zmienna, która nie będzie ponownie przypisywana?

To zależy od Ciebie / Twojego zespołu.

Czy to naprawdę robi jakąkolwiek różnicę, jeśli var is used in place ofconst` i vice versa?

Tak:

  • vari constmają różne reguły zakresu. (Być może chciał porównać letzamiast var). W szczególności: consta letto blok o zakresie i, kiedy jest stosowany w zakresie globalnym, nie tworzyć właściwości dotyczące globalnego obiektu (choć robią tworzenia globalnych). varma albo zasięg globalny (gdy jest używany w zakresie globalnym), albo zasięg funkcji (nawet jeśli jest używany w bloku), a gdy jest używany w zakresie globalnym, tworzy właściwość na obiekcie globalnym.
  • Zobacz moje „trzy przydatne rzeczy” powyżej, wszystkie dotyczą tego pytania.
TJ Crowder
źródło
1

Semantyka varilet

vari letsą instrukcją dla maszyny i innych programistów:

Zamierzam zmienić wartość tego zadania w trakcie wykonywania. Nie polegaj na ostatecznej wartości tego zadania.

Implikacje użycia varilet

vari letzmusić innych programistów do odczytania całego kodu pośredniczącego od deklaracji do ostatecznego użycia oraz uzasadnienia wartości przypisania w tym momencie wykonywania programu.

Osłabiają one rozumowanie maszynowe dla ESLint i innych usług językowych w celu prawidłowego wykrywania błędnie wpisanych nazw zmiennych w późniejszych przypisaniach i ponownego użycia zakresu nazw zmiennych zewnętrznych, w przypadku gdy zasięg wewnętrzny zapomina się zadeklarować.

Powodują także, że środowiska wykonawcze uruchamiają wiele iteracji na wszystkich ścieżkach kodowych w celu wykrycia, że ​​faktycznie są stałymi, zanim będą mogły je zoptymalizować. Chociaż jest to mniejszy problem niż wykrywanie błędów i zrozumiałość dla programistów.

Kiedy użyć const

Jeśli wartość referencji nie zmienia się w trakcie wykonywania, poprawna składnia wyrażająca zamiary programisty to const. W przypadku obiektów zmiana wartości odniesienia oznacza wskazanie na inny obiekt, ponieważ odwołanie jest niezmienne, ale obiekt nie.

constobiekty „ ”

W przypadku odniesień do obiektu wskaźnika nie można zmienić na inny obiekt, ale obiekt utworzony i przypisany do constdeklaracji można modyfikować. Możesz dodawać lub usuwać elementy z consttablicy, do której istnieje odwołanie, oraz mutować klucze właściwości w obiekcie, do którego istnieje constodwołanie.

Aby osiągnąć niezmienne obiekty (które ponownie ułatwiają zrozumienie kodu dla ludzi i maszyn), możesz Object.freezeobiekt w deklaracji / przypisaniu / tworzeniu, w następujący sposób:

const Options = Object.freeze(['YES', 'NO'])

Object.freeze ma wpływ na wydajność, ale Twój kod jest prawdopodobnie powolny z innych powodów. Chcesz to profilować.

Możesz także enkapsulować obiekt zmienny w maszynie stanów i zwracać głębokie kopie jako wartości (tak działa stan Redux i React). Zobacz Unikanie zmiennego stanu globalnego w przeglądarce JS, aby dowiedzieć się, jak zbudować to na podstawie pierwszych zasad.

Kiedy vari letsą dobrym dopasowaniem

leti varreprezentują stan zmienny. Moim zdaniem powinny być używane tylko do modelowania rzeczywistego stanu zmiennego . Rzeczy takie jak „ czy połączenie jest żywe? ”.

Najlepiej są one enkapsulowane w testowalnych maszynach stanów, które ujawniają stałe wartości, które reprezentują „ bieżący stan połączenia ”, który jest stały w dowolnym momencie, i czym tak naprawdę interesuje się reszta kodu.

Programowanie jest już wystarczająco trudne do komponowania efektów ubocznych i przekształcania danych. Przekształcenie każdej funkcji w maszynę stanu nie do przetestowania poprzez utworzenie stanu zmiennego ze zmiennymi tylko nakłada się na złożoność.

Aby uzyskać bardziej szczegółowe wyjaśnienie, zobacz Shun the Mutant - Case forconst .

Josh Wulf
źródło
0

Nie jestem ekspertem w branży kompilacji JS, ale warto powiedzieć, że v8 korzysta z flagi const

Zwykle po zadeklarowaniu i zmianie szeregu zmiennych pamięć ulega fragmentacji, a v8 przestaje działać, zatrzymuje się na kilka sekund, aby wykonać gc lub wyrzucanie elementów bezużytecznych.

jeśli zmienna zostanie zadeklarowana za pomocą const v8, możesz mieć pewność, że umieści ją w ciasnym pojemniku o stałym rozmiarze między innymi zmiennymi const, ponieważ nigdy się nie zmieni. Może także zapisać prawidłowe operacje dla tych typów danych, ponieważ typ się nie zmieni.

Żyd
źródło
0

Jeśli chodzi o decyzję między let i const , zawsze preferuj const, aby użycie było jasne w kodzie. W ten sposób, jeśli spróbujesz ponownie ustawić zmienną, pojawi się błąd. Jeśli nie ma innego wyjścia, jak to zmienić, po prostu zmień na let . Zauważ, że jak mówi Anthony , wartości nie są niezmienne (na przykład, obiekt const może mieć zmutowane właściwości).

Jeśli chodzi o var , ponieważ ES6 jest obecnie dostępny, nigdy nie użyłem go w kodzie produkcyjnym i nie mogę wymyślić dla niego przypadku użycia. Uważaj jednak, aby zmienne zadeklarowane za pomocą var nie miały zasięgu blokowego.

Tiago Martins Peres 李大仁
źródło