Wiem, że ES6 nie jest jeszcze ustandaryzowane, ale wiele przeglądarek obecnie obsługuje const
słowo kluczowe w JS.
W specyfikacji jest napisane, że:
Wartość stałej nie może ulec zmianie przez ponowne przypisanie, a stałej nie można ponownie zadeklarować. Z tego powodu, chociaż można zadeklarować stałą bez jej inicjalizacji, byłoby to bezcelowe.
a kiedy robię coś takiego:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
Widzę, że wszystko jest w porządku i xxx
nadal jest .6
yyy
[]
Ale jeśli to zrobię yyy.push(6); yyy.push(1);
, moja stała tablica została zmieniona. W tej chwili tak jest [6, 1]
i przy okazji nadal nie mogę tego zmienić yyy = 1;
.
To jest błąd, czy coś mi brakuje? Wypróbowałem to w najnowszym chrome i FF29
javascript
ecmascript-6
const
Salvador Dali
źródło
źródło
Odpowiedzi:
Dokumentacja stwierdza:
Kiedy dodajesz do tablicy lub obiektu, którego nie przypisujesz ponownie ani nie deklarujesz ponownie, stała jest już zadeklarowana i przypisana, po prostu dodajesz do „listy”, na którą ta stała wskazuje.
Więc to działa dobrze:
i to:
ale żaden z tych:
źródło
Dzieje się tak, ponieważ twoja stała faktycznie przechowuje odniesienie do tablicy. Kiedy dołączasz coś do swojej tablicy, nie modyfikujesz stałej wartości, ale tablicę, na którą wskazuje. To samo stanie się, jeśli przypiszesz obiekt do stałej i spróbujesz zmodyfikować jakąkolwiek jego właściwość.
Jeśli chcesz zablokować tablicę lub obiekt, aby nie można go było zmodyfikować, możesz użyć
Object.freeze
metody, która jest już częścią ECMAScript 5.źródło
five
ustawiona na 5 w rzeczywistości nie ma wartości 5, jest po prostu odniesieniem do liczby 5. Więc jeśli to zrobięfive++
, nie zmieniam stałej, tylko liczbę, na którą wskazuje.five
wskazuje zmienna (zmienna byłafive
kiedyś etykietą dla liczby 5, teraz wskazuje inną liczbę: 6). W przykładzie w pytaniu (i tej odpowiedzi)x
zawsze wskazuje na tę samą listę; jeślix
jest stała, nie możesz wskazać innej listy. Jedyną różnicą jest to, że ta sama lista może się powiększać lub zmniejszać; jest to możliwe tylko dla tablic i obiektów, a nie dla prymitywów.Jest to spójne zachowanie w każdym języku programowania, o którym przychodzi mi do głowy.
Rozważmy C - tablice to tylko gloryfikowane wskaźniki. Stała tablica oznacza tylko, że wartość wskaźnika się nie zmieni - ale w rzeczywistości dane zawarte pod tym adresem są wolne.
W javascript możesz wywoływać metody obiektów stałych (oczywiście - w przeciwnym razie obiekty stałe nie służyłyby zbyt wiele!) Te metody mogą mieć efekt uboczny modyfikowania obiektu. Ponieważ tablice w javascript są obiektami, to zachowanie dotyczy również ich.
Zapewniamy tylko, że stała będzie zawsze wskazywać na ten sam obiekt. Właściwości samego obiektu można dowolnie zmieniać.
źródło
Dodatkowo ważna uwaga:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
źródło
Myślę, że dałoby to większą jasność w tej kwestii: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .
Zasadniczo sprowadza się to do
const
ciągłego wskazywania w pamięci tego samego adresu. Możesz zmienić wartość przechowywaną w tym adresie, ale nie możesz zmienić również adresu, któryconst
wskazuje.Wspomniana definicja
const
będzie aktualna, gdy wskażeconst
adres, który ma wartość pierwotną. Dzieje się tak, ponieważ nie możesz przypisać do tego wartościconst
bez zmiany jego adresu (ponieważ tak działa przypisywanie wartości pierwotnych), a zmiana adresu aconst
jest niedozwolona.Tam, gdzie tak, jakby
const
wskazywał na wartość inną niż pierwotna, istnieje możliwość edycji wartości adresu.źródło
Przeszedłem przez ten artykuł, szukając, dlaczego udało mi się zaktualizować obiekt, nawet po zdefiniowaniu go jako
const
. Chodzi o to, że to nie obiekt bezpośrednio, ale atrybuty, które zawiera, mogą być aktualizowane.Na przykład mój obiekt wygląda następująco:
Powyższe odpowiedzi poprawnie wskazały, że to Object jest stałą, a nie jego atrybutem. W związku z tym będę mógł zaktualizować identyfikator lub nazwę, wykonując:
Ale nie będę mógł zaktualizować samego obiektu, jak:
źródło
Ponieważ w const można zmienić wartości obiektu, więc obiekt w rzeczywistości nie przechowuje danych przypisania, ale zamiast tego wskazuje na to. więc istnieje różnica między prymitywami a obiektami w JavaScript.
źródło