Từ khóa 'const' không làm cho giá trị bất biến. Nó có nghĩa là gì?


85

định nghĩa const trong Exploring ES6 của Tiến sĩ Axel Rauschmayer:

consthoạt động giống như let, nhưng biến bạn khai báo phải được khởi tạo ngay lập tức, với giá trị không thể thay đổi sau đó . […]

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

và sau đó anh ấy viết

Cạm bẫy: const không làm cho giá trị bất biến

const chỉ có nghĩa là một biến luôn có cùng một giá trị, nhưng nó không có nghĩa là bản thân giá trị đó tồn tại hoặc trở thành bất biến.

Tôi hơi bối rối với cạm bẫy này. Bất kỳ ai có thể xác định rõ ràng constvới cạm bẫy này?


38
Giải thích MDN rõ ràng: "Khai báo const tạo tham chiếu chỉ đọc cho một giá trị. Điều đó không có nghĩa là giá trị mà nó giữ là bất biến, chỉ là không thể gán lại mã định danh biến. Ví dụ: trong trường hợp nội dung là một đối tượng , điều này có nghĩa là bản thân đối tượng vẫn có thể bị thay đổi . " (tôi nhấn mạnh)
Gerardo Furtado

4
Nó có nghĩa là nếu giá trị có thể thay đổi, (ví dụ nếu nó là một đối tượng) thì bạn vẫn có thể thay đổi đối tượng đó (ví dụ: cập nhật, thêm, xóa thuộc tính).
Felix Kling

2
const x = "immutable"là bất biến, bởi vì Stringlà bất biến. constnghiêm cấm chỉ định lại.

3
@ibrahimmahrir: đi qua một tài liệu tham khảo (những gì hiện Javascript cho các đối tượng) là không giống như vượt qua bằng cách tham khảo (trong đó mô tả mối quan hệ giữa các ràng buộc, giá trị là không thích hợp).
Felix Kling

2
@ibrahimmahrir: Vâng, đó là vấn đề. Thuật ngữ truyền qua tham chiếu có một ý nghĩa rất cụ thể .
Felix Kling

Câu trả lời:


97

MDN tổng hợp nó một cách độc đáo:

Khai báo const tạo một tham chiếu chỉ đọc cho một giá trị. Điều đó không có nghĩa là giá trị mà nó giữ là không thay đổi, chỉ là không thể gán lại định danh biến. Ví dụ, trong trường hợp nội dung là một đối tượng, điều này có nghĩa là bản thân đối tượng vẫn có thể được thay đổi.

Ngắn gọn hơn: const tạo ra một ràng buộc bất biến.

Nói cách khác: const, giống như var, cung cấp cho bạn một đoạn bộ nhớ có thể thay đổi mà bạn đang lưu trữ thứ gì đó. Tuy nhiên, const ra lệnh rằng bạn phải tiếp tục tham chiếu đến cùng một đoạn bộ nhớ - bạn không thể gán lại biến cho một đoạn bộ nhớ khác, vì tham chiếu biến là hằng số.

Để thực sự làm cho một cái gì đó không đổi và không thay đổi sau khi bạn đã khai báo nó, bạn cần sử dụng một cái gì đó như Object.freeze(). Tuy nhiên, điều đó nông cạn và chỉ hoạt động trên các cặp khóa / giá trị. Việc đóng băng toàn bộ vật thể cần nhiều nỗ lực hơn một chút. Thực hiện lặp đi lặp lại một cách hiệu quả vẫn còn nhiều thách thức hơn. Nếu bạn thực sự cần điều đó, tôi khuyên bạn nên kiểm tra một cái gì đó như Immutable.js


20
Trong các điều kiện C: Nếu một bình thường var xlà a struct Object *xthì a const xlà a struct Object *const x. Không thể thay đổi con trỏ; thứ mà nó trỏ tới có thể.
Vụ kiện của Fund Monica vào

151

Khi bạn tạo một thứ gì đó consttrong JavaScript, bạn không thể gán lại chính biến đó để tham chiếu một thứ khác. Tuy nhiên, biến vẫn có thể tham chiếu đến một đối tượng có thể thay đổi.

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;

Trong trường hợp nguyên thủy như chuỗi và số, constdễ hiểu hơn vì bạn không thay đổi các giá trị mà thay vào đó chỉ định một giá trị mới cho biến.


18
Câu trả lời này tốt hơn nhiều so với câu được chấp nhận. Cô đọng hơn và chứa mã ví dụ thực tế. (Nói cách khác, đi vào vấn đề .) +1
jpmc26

16

Rebinding

constvà các letkhai báo kiểm soát xem có cho phép các liên kết lại (còn gọi là gán lại) giữa số nhận dạng và giá trị hay không:

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);

Bất biến

Tính bất biến được kiểm soát ở mức kiểu. Objectlà một loại có thể thay đổi, trong khi Stringlà một loại bất biến:

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 có nghĩa là: bạn không thể thay đổi giá trị được gán ban đầu.

Đầu tiên, hãy định nghĩa, giá trị trong js là gì. Giá trị có thể là: Boolean, chuỗi, số, đối tượng, hàm và giá trị không xác định.

Như: Mọi người đang gọi bạn bằng tên của bạn, nó không thay đổi. Tuy nhiên, bạn thay quần áo của bạn. Các ràng buộc giữa nhân dân và bạn là tên của bạn. Phần còn lại có thể thay đổi. Xin lỗi vì ví dụ kỳ lạ.

Vì vậy, hãy để tôi cung cấp cho bạn một số ví dụ:

// 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

Như bạn có thể thấy, trừ khi bạn không thay đổi "đầu tiên" giá trị được gán thành một hằng số, không có lỗi. Bất cứ khi nào bạn cố gắng thay đổi giá trị được chỉ định đầu tiên thành một thứ khác, nó sẽ nổi giận và xuất hiện lỗi.

Vì vậy, đây là điều thứ hai bạn có thể biết khi sử dụng const. Đó là, nó phải được khởi tạo thành một giá trị trên khai báo của nó nếu không nó sẽ tức giận.

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

0

ES6/ ES2015 consttừ khóa:

Các consttừ khóa được sử dụng để khai báo một biến có phạm vi khối (như tuyên bố với let). Sự khác biệt giữa khai báo một biến với constletnhư sau:

  1. Một biến đã khai báo constkhông thể được gán lại .
  2. Một biến được khai báo với constphải được gán khi được khai báo . Đây là hệ quả hợp lý của điểm trước vì một biến được khai báo với constkhông thể được gán lại, đó là lý do tại sao chúng ta phải gán nó chính xác một lần khi chúng ta khai báo biến .

Thí dụ:

// 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;

Trong ví dụ trên, chúng ta có thể quan sát những điều sau:

  1. Biến được myVariablekhai báo với letcó thể được khai báo trước và sau đó được gán.
  2. Biến được myConstantkhai báo với constphải được khai báo và gán cùng một lúc.
  3. Khi chúng tôi cố gắng gán lại biến, myConstantchúng tôi gặp lỗi sau:

Uncaught TypeError: Gán cho biến hằng số

Lưu ý: Biến được gán với constvẫn có thể thay đổi:

Một biến được khai báo constchỉ không thể được gán lại, nó vẫn có thể thay đổi được . Có thể thay đổi có nghĩa là cấu trúc dữ liệu (đối tượng, mảng, bản đồ, v.v.) được gán cho constbiến vẫn có thể bị thay đổi (tức là bị thay đổi). Ví dụ về đột biến là:

  1. Thêm / xóa / thay đổi thuộc tính của một đối tượng
  2. Thay đổi giá trị của một mảng tại một chỉ mục mảng cụ thể

Nếu thực sự muốn một đối tượng không thể thay đổi, bạn sẽ phải sử dụng một cái gì đó như Object.freeze(). Đây là một phương pháp đóng băng một đối tượng. Không thể thay đổi đối tượng được đóng băng và không thể thêm thuộc tính mới.

Thí dụ:

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);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.