Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Ý nghĩa của "Giá trị nguyên thủy bất biến" trong JavaScript là gì?

Trong JavaScript, bạn thường nghe rằng các giá trị nguyên thủy (primitive) là bất biến (immutable), khác với giá trị phi nguyên thủy (non-primitive) là có thể biến đổi (mutable). Việc hiểu sự khác biệt giữa các loại giá trị này (còn gọi là kiểu dữ liệu) rất quan trọng vì nó sẽ giúp bạn tránh nhiều đau đầu sau này.

Các giá trị nguyên thủy bao gồm:

  • số (numbers)
  • chuỗi (strings)
  • boolean

Các giá trị phi nguyên thủy bao gồm:

  • đối tượng (objects)
  • hàm (functions)

Mutable có nghĩa là có thể thay đổi.

Immutable có nghĩa là không thể thay đổi.

Giá trị phi nguyên thủy là mutable (có thể thay đổi)

Dưới đây là danh sách (mảng) các người được gán cho một biến:

let peopleList = ['Arnold', 'Linda', 'Sylvester', 'Dolph']

Giờ tôi muốn biến đổi danh sách của mình. Biến đổi đơn giản nghĩa là thay đổi. Tôi muốn thay Arnold bằng Jean-Claude, và in kết quả:

let peopleList = ['Arnold', 'Linda', 'Sylvester', 'Dolph'] peopleList[0] = 'Jean-Claude' console.log(peopleList)

Đã thành công! Chúng ta vừa thực hiện một phép biến đổi trên giá trị hiện có. Trong trường hợp này, giá trị hiện có là một mảng (danh sách), hoặc cụ thể hơn là một đối tượng mảng.

Trong JavaScript, các giá trị phi nguyên thủy là mutable (có thể thay đổi).

Giá trị nguyên thủy là immutable (không thể thay đổi)

Dưới đây là giá trị văn bản (chuỗi) được gán cho một biến:

let person = 'Ernold'

Chết, tiếc thay, chúng ta đánh vần sai Arnold bằng cách dùng E thay vì A ở chữ cái đầu. Hãy sửa nhanh và in kết quả:

let person = 'Ernold' person[0] = 'A' console.log(person) // output: Ernold

Sao lại thế? Tại sao nó in ra "Ernold"? Chúng ta vừa đổi E thành A à!?

Không, vì giá trị chúng ta đang cố biến đổi là một chuỗi, là một giá trị nguyên thủy — và tất cả giá trị nguyên thủy đều immutable (không thể thay đổi).

Chỉ có giá trị phi nguyên thủy (đối tượng & hàm) mới mutable.

Bối rối?

Bình thường thôi khi mới học JavaScript mà bối rối về chuyện này, vì bề ngoài các ví dụ trông và hành xử tương tự — trong một số tình huống.

Hãy in tên đầu tiên từ mảng trước:

let peopleList = ['Arnold', 'Linda', 'Sylvester', 'Dolph'] console.log(peopleList[0]) // output: "Arnold"

Không ngạc nhiên, nó in ra "Arnold".

Giờ in chữ cái đầu của chuỗi trước (tên sai chính tả):

let person = 'Ernold' console.log(person[0]) // output: ??

Bạn nghĩ sẽ xảy ra gì?

...

...

Nó chạy! Nó in ra "E"!

Bạn có mong đợi nó không chạy không?

Dù sao, bài học quan trọng là bạn có thể truy cập giá trị nguyên thủy giống như truy cập giá trị phi nguyên thủy, nhưng bạn không thể thay đổi (biến đổi) nó. Đó là sự khác biệt lớn (truy cập vs biến đổi).

Trong JavaScript, giá trị nguyên thủy là chỉ đọc (read-only), trong khi giá trị phi nguyên thủy (đối tượng/mảng, hàm) vừa đọc vừa ghi (read & write).

Đó là lý do chúng ta có thể thay đổi (biến đổi) giá trị mục đầu tiên của mảng từ Arnold thành Jean-Claude trước, nhưng không thể sửa lỗi chính tả đơn giản từ "Ernold" thành "Arnold" — vì nó là chuỗi, và chuỗi/giá trị nguyên thủy là immutable.

Biến vs Giá trị

(Tôi biết một số bạn đang nghĩ gì)

Dù vừa kết luận giá trị nguyên thủy là immutable, tôi vẫn quyết tâm sửa lỗi chính tả "Ernold". Hãy thử cái mới!

Xem mã sau (đọc kỹ):

let person = 'Ernold' person = 'Arnold' console.log(person) // output: ??

Căn cứ vào những gì bạn vừa học về giá trị nguyên thủy như chuỗi, bạn nghĩ mã trên sẽ in ra Arnold, có hay không?

...

(Suy nghĩ xem)

...

Nó in ra Arnold!

Một số bạn đã biết tại sao, nhưng nếu chưa, đó là bình thường, bạn sẽ có "phút chốc hiểu ra" ngay. Đọc đoạn sau kỹ:

Mã trên chạy vì chúng ta không biến đổi giá trị chuỗi, thậm chí không chạm đến nó. Thay vào đó, chúng ta gán một giá trị chuỗi mới gọi là 'Arnold' cho biến person nên nó không còn tham chiếu (trỏ tới) giá trị chuỗi 'Ernold'.

Giá trị nguyên thủy không thể thay đổi, nhưng biến có thể!

Biến không phải là giá trị, nên quy tắc về tính biến đổi/bất biến không áp dụng như nhau. Biến chỉ trỏ tới giá trị.

Chúng ta chưa bao giờ chạm trực tiếp vào giá trị chuỗi cũ 'Ernold', chỉ bảo biến person trỏ tới chuỗi khác tên 'Arnold' rồi dùng console.log() in kết quả.

Một số bạn có thể nghĩ tôi đang "đập chết ngựa" ở đây, nhưng việc nhận ra cách JavaScript hoạt động này rất quan trọng. Lặp lại là bạn tốt.

Lưu ý: kiểu biến dùng xuyên suốt hướng dẫn này là từ khóa let — là mutable, như bạn vừa thấy. Nếu dùng biến const, tình huống sẽ khác — nhưng tôi sẽ dành cho hướng dẫn khác.

Tóm lại:

Trong JavaScript:

  • giá trị phi nguyên thủy có thể tham chiếu, truy cập — và biến đổi.
  • giá trị nguyên thủy có thể tham chiếu, truy cập — nhưng không thể biến đổi.
  • biến và giá trị là hai thứ khác nhau, áp dụng quy tắc khác nhau.