Có thể thay đổi và không thể thay đổi trong JavaScript
Bài viết này giải thích các khái niệm có thể thay đổi và không thể thay đổi trong JavaScript.
YouTube Video
Có thể thay đổi và không thể thay đổi trong JavaScript
Có thể thay đổi là gì?
Có thể thay đổi nghĩa là một giá trị có thể được chỉnh sửa. Đối tượng và mảng, thuộc loại tham chiếu, là các ví dụ điển hình về cấu trúc dữ liệu có thể thay đổi.
Ví dụ về một đối tượng có thể thay đổi
1let person = { name: "Alice", age: 25 };
2person.age = 26;
3console.log(person); // { name: "Alice", age: 26 }
Trong đoạn mã này, thuộc tính age
của đối tượng person
được thay đổi từ 25
thành 26
. Vì các đối tượng được truyền bằng tham chiếu, nội dung tại địa chỉ bộ nhớ được lưu trong biến person
sẽ bị thay đổi.
Ví dụ về một mảng có thể thay đổi
1let numbers = [1, 2, 3];
2numbers.push(4);
3console.log(numbers); // [1, 2, 3, 4]
Trong đoạn mã này, phương thức push
được sử dụng để thêm một phần tử mới 4
vào mảng gốc. Điều này chỉnh sửa mảng gốc, làm cho nó trở thành một thao tác có thể thay đổi.
Ví dụ trong một hàm
1// Function to append a value to an array
2function append(arr, value) {
3 arr.push(value); // Modify the original array
4 console.log(arr);
5}
6
7let numbers = [1, 2, 3];
8append(numbers, 4);
9
10console.log(numbers); // [1, 2, 3, 4] (original array is modified)
Khi thực hiện các thao tác có thể thay đổi bên trong một hàm, mảng gốc cũng sẽ bị thay đổi.
Không thể thay đổi là gì?
Không thể thay đổi nghĩa là một giá trị không thể bị chỉnh sửa. Các loại dữ liệu nguyên thủy về cơ bản là không thể thay đổi.
Ví dụ về một loại dữ liệu nguyên thủy không thể thay đổi
1let str = "hello";
2str[0] = "H";
3console.log(str); // "hello"
Cố gắng thay đổi ký tự đầu tiên của chuỗi str
thành H
sẽ thất bại vì chuỗi là không thể thay đổi.
Ví dụ trong một hàm
1// Function to increment a number
2function increment(num) {
3 num++; // This modifies only the local copy of num
4 console.log(num);
5}
6
7let number = 10;
8increment(number);
9
10console.log(number); // 10 (original number remains unchanged)
Vì các số là không thể thay đổi, các thao tác bên trong hàm không ảnh hưởng đến biến gốc.
Các thao tác không thể thay đổi trên mảng
Mảng là có thể thay đổi, nhưng tạo một mảng mới thay vì chỉnh sửa mảng gốc cho phép thực hiện các thao tác không thể thay đổi.
1// Create an array of numbers
2let numbers = [1, 2, 3];
3
4// Create a new array by spreading the original and adding a new element
5let newNumbers = [...numbers, 4];
6
7console.log(numbers); // [1, 2, 3] (original array is unchanged)
8console.log(newNumbers); // [1, 2, 3, 4] (new array with an added element)
Tại đây, cú pháp trải rộng (...
) được sử dụng để tạo một mảng mới newNumbers
. Vì mảng numbers
gốc không bị thay đổi, đây là một thao tác bất biến.
Lợi ích của việc sử dụng cấu trúc dữ liệu bất biến
Cải thiện tính dự đoán
Vì dữ liệu bất biến không thể thay đổi, các sửa đổi không mong muốn ít xảy ra hơn, giảm nguy cơ lỗi.
Tương thích với các thư viện dựa trên tính bất biến
Các thư viện như React
và Redux
thường được thiết kế với dữ liệu bất biến, giúp quản lý trạng thái dễ dàng hơn khi được sử dụng đúng cách.
Tạo đối tượng bất biến bằng Object.freeze
Object.freeze
có thể được sử dụng để ngăn chặn các thay đổi đối với một đối tượng.
1// Create a frozen object (properties cannot be modified)
2const person = Object.freeze({ name: "Alice", age: 25 });
3
4// Attempt to modify a property (ignored in non-strict mode, error in strict mode)
5person.age = 26;
6
7console.log(person); // { name: "Alice", age: 25 }
Tuy nhiên, Object.freeze
thực hiện một đóng băng nông, có nghĩa là các thuộc tính của các đối tượng lồng nhau vẫn có thể thay đổi được.
1// Create a frozen object with a nested object
2const user = Object.freeze({ profile: { name: "Bob" } });
3
4// Attempt to modify a nested property (this works because Object.freeze() is shallow)
5user.profile.name = "Charlie";
6
7console.log(user.profile.name); // "Charlie" (nested object is still mutable)
Để tạo một đối tượng hoàn toàn bất biến, cần phải thực hiện đóng băng sâu.
1// Function to deeply freeze an object, making all nested objects immutable
2function deepFreeze(obj) {
3 Object.keys(obj).forEach(key => {
4 if (typeof obj[key] === "object" && obj[key] !== null) {
5 deepFreeze(obj[key]); // Recursively freeze nested objects
6 }
7 });
8 return Object.freeze(obj); // Freeze the top-level object
9}
10
11// Create a deeply frozen object
12const user = deepFreeze({ profile: { name: "Bob" } });
13
14// Attempt to modify a nested property (ignored)
15user.profile.name = "Charlie";
16
17console.log(user.profile.name); // "Bob" (unchanged due to deep freeze)
Tóm tắt
- Dữ liệu có thể thay đổi có thể được chỉnh sửa, bao gồm đối tượng và mảng.
- Dữ liệu bất biến không thể được thay đổi, bao gồm các kiểu nguyên thủy như chuỗi và số.
- Sử dụng cú pháp trải rộng hoặc
map
cho phép thực hiện thao tác dữ liệu bất biến.. Object.freeze
vàdeepFreeze
có thể được sử dụng để ngăn chặn các thay đổi đối với đối tượng.- Sử dụng dữ liệu bất biến giúp mã dễ dự đoán hơn và ít lỗi hơn.
Thiết kế bất biến tăng cường độ an toàn và khả năng đọc mã, vì vậy hãy tận dụng nó thật tốt!
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.