0
0
Lập trình
TT

Sự khác biệt giữa `readonly` và `const` trong TypeScript

Đăng vào 7 tháng trước

• 4 phút đọc

🔒 Sự khác biệt giữa readonlyconst trong TypeScript

Khi học TypeScript, một trong những nhầm lẫn thường gặp là:

👉 “Khi nào tôi nên sử dụng const và khi nào tôi nên sử dụng readonly?”

Nhìn qua, cả hai từ khóa có vẻ như có nghĩa giống nhau: "không thể thay đổi".
Nhưng thực tế, chúng hoạt động trong các ngữ cảnh khác nhau và phục vụ các mục đích khác nhau.

Trong bài viết này, chúng ta sẽ khám phá:

  • constreadonly thực sự có nghĩa là gì
  • Sự khác biệt chính với các ví dụ
  • Các trường hợp sử dụng trong biến, đối tượng, mảng và lớp
  • Một bảng tóm tắt để tham khảo nhanh

1. const trong TypeScript

Từ khóa const được sử dụng để khai báo các biến không thể được gán lại.

Ví dụ:

typescript Copy
const x = 10;
// x = 20; ❌ Lỗi: không thể gán lại biến const

🔑 Quan trọng: const ngăn chặn việc gán lại liên kết, nhưng không ngăn chặn việc biến đổi đối tượng mà nó tham chiếu đến.

typescript Copy
const user = { name: "Alice" };
user.name = "Bob"; // ✅ Cho phép
// user = { name: "Charlie" }; ❌ Không cho phép

Vì vậy, nếu một biến const giữ một đối tượng, bạn vẫn có thể cập nhật các thuộc tính của nó.


2. readonly trong TypeScript

Từ khóa readonly áp dụng cho các thuộc tính bên trong đối tượng, lớp và mảng.
Nó ngăn chặn việc sửa đổi thuộc tính đó, nhưng không ngăn chặn việc gán lại biến chứa đối tượng.

Ví dụ với Đối tượng:

typescript Copy
type User = {
  readonly name: string;
  age: number;
};

let user: User = { name: "Alice", age: 25 };

user.age = 26; // ✅ Cho phép
// user.name = "Bob"; ❌ Lỗi: không thể gán cho thuộc tính readonly

Ví dụ với Lớp:

typescript Copy
class Person {
  readonly id: number; // thuộc tính không thay đổi

  constructor(id: number) {
    this.id = id;
  }
}

const p = new Person(101);
// p.id = 202; ❌ Không cho phép

Ở đây, id không thay đổi sau khi được gán trong constructor.


3. So sánh constreadonly với Mảng

Đây là một mẹo phỏng vấn phổ biến! Hãy so sánh.

Mảng const

typescript Copy
const numbers = [1, 2, 3];

numbers.push(4);   // ✅ Cho phép
// numbers = [5, 6]; ❌ Không cho phép
  • Bạn có thể sửa đổi nội dung.
  • Bạn không thể gán lại biến đó.

Mảng readonly

typescript Copy
const readonlyNumbers: readonly number[] = [1, 2, 3];

// readonlyNumbers.push(4); ❌ Không cho phép
// readonlyNumbers[0] = 100; ❌ Không cho phép
  • Bạn không thể sửa đổi nội dung của mảng.
  • Bạn vẫn có thể gán lại nếu nó không được khai báo bằng const:
typescript Copy
let arr: readonly number[] = [1, 2, 3];
arr = [4, 5, 6]; // ✅ Cho phép

4. Nơi áp dụng

  • const: Biến cấp cao, bên trong hàm, vòng lặp hoặc khối.
  • readonly: Các thuộc tính đối tượng, thành viên lớp và mảng (như kiểu).
typescript Copy
// biến const
const pi = 3.14;

// thuộc tính readonly
type Circle = {
  readonly radius: number;
};

5. Thời gian biên dịch so với Thời gian chạy

Một sự khác biệt lớn khác là cách chúng tồn tại tại thời gian chạy:

  • const → Tồn tại trong thời gian chạy JavaScript.
  • readonly → Chỉ có TypeScript, biến mất trong thời gian chạy.

Ví dụ:

typescript Copy
const x = 10; // trong JS: const x = 10;

type User = { readonly name: string };
let u: User = { name: "Alice" };
// tại thời gian chạy → chỉ là một đối tượng thông thường

Vì vậy, readonly chỉ là một bảo đảm thời gian biên dịch.


6. Các trường hợp sử dụng thực tế

Sử dụng const khi khai báo các biến mà bạn không muốn gán lại:

typescript Copy
const API_URL = "https://api.example.com";
const MAX_RETRIES = 3;

Sử dụng readonly khi mô hình hóa cấu trúc dữ liệu mà thuộc tính không nên thay đổi sau khi khởi tạo:

typescript Copy
interface Config {
  readonly apiKey: string;
  readonly version: number;
}

const config: Config = {
  apiKey: "abc123",
  version: 1
};

// config.apiKey = "xyz789"; ❌ Không cho phép

Kết hợp cả hai để tăng cường an toàn:

typescript Copy
const users: readonly string[] = ["Alice", "Bob", "Charlie"];
// users.push("David"); ❌ Không cho phép

7. Tóm tắt sự khác biệt: Bảng tóm tắt

Tính năng const readonly
Áp dụng cho Biến (liên kết) Thuộc tính đối tượng, trường lớp, mảng
Ngăn chặn Gán lại biến Thay đổi thuộc tính/phần tử mảng
Phạm vi Hàm, khối, biến toàn cục Kiểu đối tượng, lớp, mảng
Tác động thời gian chạy Tồn tại trong JavaScript (ES6 const) Chỉ có TypeScript (chỉ thời gian biên dịch)
Biến đổi đối tượng Cho phép (thuộc tính có thể thay đổi) Ngăn ngừa việc thay đổi thuộc tính
Biến đổi mảng Cho phép (push, pop, v.v.) Ngăn chặn (readonly number[])

🔑 Suy nghĩ cuối cùng

  • Sử dụng const khi bạn muốn khóa một liên kết biến.
  • Sử dụng readonly khi bạn muốn làm cho thuộc tính đối tượng hoặc mảng không thay đổi.
  • Kết hợp cả hai để có các mẫu không thay đổi mạnh mẽ trong TypeScript.

👉 Tóm lại:

  • const = bất biến cấp biến
  • readonly = bất biến cấp thuộc tính

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào