Ключове слово 'const' не робить значення незмінним. Що це означає?


85

Там це визначення Const в Досліджуючи ES6 доктором Акселем Rauschmayer:

constпрацює як let, але заявлену змінну потрібно негайно ініціалізувати зі значенням, яке згодом не можна змінити . […]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

а потім він пише

Підводний камінь: const не робить значення незмінним

const означає лише, що змінна завжди має однакове значення, але це не означає, що саме значення є або стає незмінним.

Я мало заплутаний у цій пастці. Чи може хтось чітко визначити це constз цим підводним каменем?


38
MDN пояснення ясно: «Декларація Const створює тільки для читання посилання на значення Це не означає , що значення, яке має незмінний, так що ідентифікатор змінної не може бути перепризначений , наприклад, в разі , якщо зміст є .. Об'єкт , це означає, що сам об'єкт все ще може бути змінений ". (наголос на моєму)
Херардо Фуртадо

4
Це означає, що якщо значення можна змінювати (наприклад, якщо це об’єкт), ви все одно можете мутувати цей об’єкт (наприклад, оновити, додати, видалити властивості).
Фелікс Клінг,

2
const x = "immutable"є незмінним, оскільки Stringє незмінним. constзабороняє просто перепризначення.

3
@ibrahimmahrir: передача в засланні (що робить JavaScript для об'єктів) не є таким же , як прохід по посиланню (яка описує взаємозв'язок між кріпленнями, значення не має значення).
Фелікс Клінг,

2
@ibrahimmahrir: Так, це питання. Термін передача-посилання має цілком конкретне значення .
Фелікс Клінг,

Відповіді:


97

MDN це чудово підсумовує:

Оголошення const створює посилання лише на читання на значення. Це не означає, що значення, яке він має, є незмінним, просто те, що ідентифікатор змінної не може бути перепризначений. Наприклад, якщо вміст є об'єктом, це означає, що сам об'єкт все ще може бути змінений.

Коротше: const створює незмінне зв’язування.

Іншими словами: const, як і var, дає вам змінний шматок пам'яті, в якому ви щось зберігаєте. Однак const диктує, що ви повинні продовжувати посилатися на той самий шматок пам'яті - ви не можете перепризначити змінну іншому шматку пам'яті, оскільки посилання на змінну є постійним.

Щоб дійсно зробити щось постійне і незмінне після того, як ви це заявили, вам потрібно використовувати щось на зразок Object.freeze(). Однак це неглибоко і працює лише на парах ключ / значення. Заморожування цілого об'єкта вимагає трохи більше зусиль. Зробити це багато разів ефективніше - це ще складніше. Якщо у вас дійсно є потреба в цьому, я рекомендую перевірити щось на зразок Immutable.js


20
З точки зору C: Якщо нормальним var xє a struct Object *x, a const xє a struct Object *const x. Покажчик не можна змінити; те, на що він вказує, може.
Позов до Моніки

151

Коли ви робите щось constу JavaScript, ви не можете перепризначити саму змінну для посилання на щось інше. Однак змінна все ще може посилатися на змінний об'єкт.

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

У випадку примітивів, таких як рядки та числа, constпростіше зрозуміти, оскільки ви не мутуєте значення, а замість цього призначаєте нове значення змінній.


18
Ця відповідь набагато краща за прийняту. Більш стислий і містить фактичний приклад коду. (Іншими словами, переходить до
суті

16

Перев’язування

constі letдекларації контролюють, чи дозволено повторне прив'язування (воно ж перепризначення) між ідентифікаторами та значеннями:

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

Незмінність

Незмінність контролюється на рівні типу. Objectє змінним типом, тоді як Stringє незмінним типом:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


1

const означає: ви не можете змінити початково призначене значення.

Спочатку визначте, що таке значення в js. Значення може бути: логічні значення, рядки, числа, об'єкти, функції та невизначені значення.

Як: Люди телефонують вам з вашим ім’ям, це не змінюється. Однак ви переодягаєтесь. Зв'язування між людьми , і ви це ваше ім'я. Решта може змінитися. Вибачте за дивний приклад.

Отже, дозвольте навести кілька прикладів:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

Як бачите, якщо ви не зміните "перше" присвоєне значення на const, помилок не буде. Щоразу, коли ви намагаєтесь змінити перше призначене значення на щось інше, воно злиться і видає помилку.

Отже, це друге, що ви можете знати під час використання const. Що означає, його слід ініціалізувати до значення у його декларації, інакше це буде сердитися.

const orphan;                    // error
const rich = 0;                  // no error

0

ES6/ ES2015 constключове слово:

constВикористовується ключове слово , щоб оголосити змінну Scoped блок (наприклад , оголосити з let). Різниця між оголошенням змінної за допомогою constі letполягає в наступному:

  1. Заявлену змінну constнеможливо перепризначити .
  2. Змінна, оголошена з const, повинна бути призначена при оголошенні . Це логічний наслідок попереднього пункту, тому що змінна, оголошена з, constне може бути перепризначена, тому нам слід призначити її рівно один раз, коли ми оголошуємо змінну .

Приклад:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

У наведеному вище прикладі ми можемо спостерігати наступне:

  1. Змінна, myVariableоголошена з, letможе бути спочатку оголошена, а потім призначена.
  2. Змінна, myConstantоголошена з const, повинна бути оголошена і призначена одночасно.
  3. При спробі перепризначити змінну myConstantми отримуємо таку помилку:

Uncaught TypeError: Присвоєння константі змінної

Застереження: Змінна, призначена параметром const, все ще змінюється:

Змінна, оголошена constпросто не може бути перепризначена, вона все ще змінюється . Будучи змінним означає, що структура даних (об’єкт, масив, карта тощо), яка була призначена constзмінній, все ще може бути змінена (тобто мутована). Прикладами мутації є:

  1. Додавання / видалення / зміна властивості об’єкта
  2. Зміна значення масиву за певним індексом масиву

Якщо ви дійсно хочете, щоб об'єкт не змінювався, вам доведеться використовувати щось на зразок Object.freeze(). Це метод, який заморожує об'єкт. Заморожений об'єкт більше не можна змінювати, а також не можна додавати нові властивості.

Приклад:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.