Giải thích biến JavaScript: var vs let vs const, Phạm vi và Các thực tiễn tốt nhất

1. Giới thiệu

JavaScript là một trong những ngôn ngữ lập trình được sử dụng rộng rãi nhất trong phát triển web. Đặc biệt, trong phát triển front-end, nó là yếu tố thiết yếu để xây dựng các trang web tương tác. Trong bối cảnh đó, biến đóng vai trò quan trọng trong việc quản lý dữ liệu trong các chương trình của bạn.

Trong bài viết này, chúng tôi sẽ giải thích chi tiết về các biến trong JavaScript — từ những kiến thức cơ bản đến các chủ đề nâng cao hơn. Cụ thể, bạn sẽ học cách khai báo biến, hiểu các khái niệm về phạm vi, tuân thủ quy tắc đặt tên và ngăn ngừa các lỗi thường gặp, tất cả đều kèm theo các ví dụ mã thực tế.

1.1 Những gì bạn sẽ học trong bài viết này

Bằng cách đọc bài viết này, bạn sẽ nắm được các kiến thức và kỹ năng sau.

  1. Hiểu khái niệm cơ bản và vai trò của biến trong JavaScript
  2. Tìm hiểu sự khác nhau giữa var, letconst và cách sử dụng chúng một cách đúng đắn
  3. Quản lý phạm vi (scope) và thời gian tồn tại một cách hiệu quả
  4. Áp dụng biến với các kỹ thuật thực tiễn thông qua các ví dụ mã thực tế
  5. Xác định các nguyên nhân lỗi phổ biến và học cách khắc phục chúng

1.2 Đối tượng đọc bài viết này

  • Người mới bắt đầu muốn học các kiến thức cơ bản về JavaScript
  • Người học trung cấp đã có kinh nghiệm lập trình nhưng muốn hiểu sâu hơn về sự khác nhau của các biến và phạm vi
  • Bất kỳ ai muốn giảm thiểu lỗi lập trình và thiết kế chương trình hiệu quả hơn

Hướng dẫn này giải thích các khái niệm kèm theo ví dụ mã để người mới không bị mắc kẹt. Nó cũng bao gồm các mẹo ngăn ngừa lỗi và một phần FAQ để người học trung cấp có thể thu thập kiến thức thực tiễn, áp dụng ngay.

Trong phần tiếp theo, chúng ta sẽ xem xét kỹ hơn về “biến” là gì ngay từ đầu.

2. Biến là gì trong JavaScript?

Trong JavaScript, một biến là một container có tên được dùng để tạm thời lưu trữ dữ liệu và tái sử dụng khi cần. Việc sử dụng biến giúp quản lý dữ liệu trong chương trình trở nên hiệu quả hơn.

2.1 Vai trò của một biến là gì?

Trong lập trình, một biến giống như một “hộp” lưu trữ thông tin. Bằng cách đưa dữ liệu vào hộp và lấy ra, bạn có thể quản lý trạng thái chương trình và thực hiện các phép tính.

Ví dụ, đoạn mã sau sử dụng một biến để hiển thị một thông điệp.

let greeting = "Hello!";
console.log(greeting);

Trong đoạn mã này:

  • Biến greeting lưu trữ chuỗi "Hello!".
  • console.log() xuất nội dung của biến đó.

Đây là cách các biến cho phép bạn thao tác dữ liệu một cách động trong chương trình.

2.2 Các đặc điểm chính của biến trong JavaScript

Các biến trong JavaScript có các đặc điểm sau.

  1. Kiểu động
  • Trong JavaScript, kiểu của biến (số, chuỗi, mảng, v.v.) được xác định tự động. Bạn không cần chỉ định kiểu khi khai báo biến.
  • Ví dụ:
    let number = 10;         // number
    let text = "Hello!";     // string
    let isTrue = true;       // boolean
    
  1. Tính linh hoạt
  • Bạn có thể gán các giá trị có kiểu khác nhau cho cùng một biến (mặc dù không được khuyến khích vì tính dễ đọc).
  • Ví dụ:
    let data = 10;     // number
    data = "string";   // changed to string
    
  1. Phạm vi (visibility)
  • Phạm vi sử dụng của một biến phụ thuộc vào nơi nó được khai báo (chi tiết sẽ được đề cập sau).
  1. Gán lại và khai báo lại
  • Việc cho phép gán lại hoặc khai báo lại phụ thuộc vào từ khóa bạn sử dụng.
  • Ví dụ:
    var x = 5;
    var x = 10; // redeclaration allowed (not recommended)
    
    let y = 5;
    // let y = 10; // Error (cannot redeclare)
    
    const z = 5;
    // z = 10; // Error (cannot reassign)
    

2.3 Lợi ích của việc sử dụng biến

  1. Tính tái sử dụng
  • Nếu bạn cần sử dụng cùng một giá trị nhiều lần, việc lưu trữ nó trong một biến sẽ giúp quản lý dễ dàng hơn.
  1. Dễ dàng cập nhật
  • Bằng cách cập nhật giá trị của biến, các thay đổi sẽ được phản ánh trong toàn bộ chương trình.
  1. Cải thiện khả năng đọc và bảo trì
  • Sử dụng các biến có tên rõ ràng giúp làm sáng tỏ ý định và giúp các nhà phát triển khác hiểu mã của bạn.

2.4 Một ví dụ đơn giản sử dụng biến

Dưới đây là một chương trình tính toán cơ bản sử dụng biến.

.`` let price = 500; // item price let quantity = 3; // quantity let total = price * quantity; // calculate total console.log(Total is ${total} yen.`);

Trong ví dụ này, giá và số lượng được lưu trong các biến, và tổng số tiền được tính một cách động và hiển thị. Đây là cách các biến tăng tính linh hoạt và hiệu quả trong chương trình của bạn.







## 3. Cách khai báo biến và sự khác biệt giữa các từ khóa



Trong JavaScript, bạn sử dụng ba từ khóa để khai báo biến: **var**, **let**, và **const**. Hiểu các đặc điểm của chúng và cách lựa chọn giữa chúng giúp ngăn ngừa lỗi và cải thiện khả năng đọc.



### 3.1 Sự khác biệt cơ bản giữa var, let và const



#### 1. var – Khai báo truyền thống



`var` đã được sử dụng từ các phiên bản đầu của JavaScript.



**Đặc điểm:**



* Cho phép khai báo lại và gán lại.
* Có phạm vi hàm (phạm vi khối bị bỏ qua).
* Hoisting di chuyển khai báo lên đầu phạm vi của nó.



**Ví dụ:**

var x = 10; console.log(x); // 10

var x = 20; // redeclaration allowed console.log(x); // 20

if (true) { var y = 30; // ignores block scope } console.log(y); // 30

**Ghi chú:**



* Vì nó bỏ qua phạm vi khối, có thể gây ra hành vi không mong muốn.
* Nó được coi là lỗi thời trong JavaScript hiện đại; tránh sử dụng trong mã mới.



#### 2. let – Lựa chọn đề xuất cho việc gán lại



`let` được giới thiệu trong ES6 (2015) và hiện nay được sử dụng rộng rãi.



**Đặc điểm:**



* Không thể khai báo lại, nhưng có thể gán lại.
* Có phạm vi khối.
* Hoisting xảy ra, nhưng sử dụng trước khi khởi tạo sẽ gây lỗi ( **Temporal Dead Zone** ).



**Ví dụ:**

let a = 10; console.log(a); // 10

a = 20; // reassignment allowed console.log(a); // 20

if (true) { let b = 30; // valid only inside this block console.log(b); // 30 } // console.log(b); // Error: b is out of scope

**Ghi chú:**



* Sử dụng `let` khi cần gán lại, nhưng ưu tiên `const` khi bạn không cần gán lại.



#### 3. const – Dành cho hằng số



`const` cũng được giới thiệu trong ES6 và được dùng để khai báo hằng số (giá trị không nên được gán lại).



**Đặc điểm:**



* Không thể khai báo lại hoặc gán lại.
* Có phạm vi khối.
* Phải được khởi tạo ngay khi khai báo.



**Ví dụ:**

const pi = 3.14; console.log(pi); // 3.14

// pi = 3.1415; // Error: cannot reassign

if (true) { const gravity = 9.8; console.log(gravity); // 9.8 } // console.log(gravity); // Error: out of scope

**Ghi chú:**



* Bạn không thể gán lại chính biến, nhưng nếu nó là một đối tượng hoặc mảng, bạn vẫn có thể sửa đổi các thuộc tính/phần tử của nó.



**Ví dụ:**

const user = { name: “Alice” }; user.name = “Bob”; // property mutation is allowed console.log(user.name); // Bob

### 3.2 Bảng so sánh: var vs let vs const


Featurevarletconst
RedeclarationAllowedNot allowedNot allowed
ReassignmentAllowedAllowedNot allowed
ScopeFunction scopeBlock scopeBlock scope
HoistingDeclaration + initialization behavior differsDeclaration only (no safe use before init)Declaration only (no safe use before init)
Recommended?Not recommendedRecommendedRecommended
### 3.3 Cách chọn đúng 1. **Sử dụng const làm mặc định** * Nếu bạn không cần gán lại, hãy dùng `const` để tăng độ an toàn. 2. **Chỉ dùng let khi cần gán lại** * Dùng nó cho các biến đếm vòng lặp hoặc biến trạng thái cần thay đổi theo thời gian. 3. **Tránh var** * Bạn có thể thấy nó trong mã cũ, nhưng không được khuyến nghị cho các dự án hiện đại. ### 3.4 Tóm tắt nhanh cách sử dụng

const PI = 3.14; // constant let count = 0; // value that changes for (let i = 0; i < 5; i++) { count += i; } console.log(count); // display total


let userName = “Alice”; console.log(userName); // “Alice” userName = “Bob”; console.log(userName); // “Bob”

## 4. Phạm vi và vòng đời của biến



Trong JavaScript, việc hiểu **phạm vi** (nơi biến có thể được truy cập) và **vòng đời** (thời gian biến tồn tại trong bộ nhớ) của một biến là vô cùng quan trọng. Khi nắm vững các khái niệm này, bạn có thể tránh các lỗi không mong muốn và viết mã hiệu quả hơn.



### 4.1 Phạm vi là gì?

.Scope đề cập đến khoảng mà một biến có thể được truy cập. Trong JavaScript, phạm vi khác nhau tùy thuộc vào cách biến được khai báo.



#### 1. Phạm vi toàn cục



Phạm vi toàn cục có nghĩa là một phạm vi có thể được truy cập từ bất kỳ nơi nào trong chương trình.



**Example:**

var globalVar = “Global variable”;

function showGlobalVar() { console.log(globalVar); // Accessible }

showGlobalVar(); console.log(globalVar); // Accessible

**Ghi chú:**  
Vì các biến toàn cục có thể được truy cập từ bất kỳ nơi nào, chúng dễ bị xung đột tên và ghi đè không mong muốn. Bạn nên giữ chúng ở mức tối thiểu.



#### 2. Phạm vi cục bộ



Phạm vi cục bộ đề cập đến một phạm vi chỉ hợp lệ bên trong một hàm hoặc khối cụ thể.



**Example:**

function localExample() { let localVar = “Local variable”; console.log(localVar); // Accessible }

// console.log(localVar); // Error: out of scope

Trong ví dụ này, biến `localVar` chỉ có thể được truy cập bên trong hàm và không thể được tham chiếu bên ngoài nó.



#### 3. Phạm vi khối



Các biến được khai báo bằng `let` và `const` chỉ hợp lệ bên trong một khối (phần được bao bọc trong `{}`).



**Example:**

{ let blockVar = “Block scope”; console.log(blockVar); // Accessible } // console.log(blockVar); // Error: out of scope

**Quan trọng:**  
Nếu bạn khai báo một biến bằng `var`, phạm vi khối sẽ bị bỏ qua, vì vậy hãy cẩn thận.

{ var blockVar = “Block scope ignored”; } console.log(blockVar); // Accessible (not recommended)

### 4.2 Thời gian tồn tại là gì?



Thời gian tồn tại đề cập đến thời gian một biến tiếp tục tồn tại trong bộ nhớ.



1. **Thời gian tồn tại của các biến toàn cục**


* Chúng tồn tại từ khi chương trình bắt đầu cho đến khi kết thúc.


1. **Thời gian tồn tại của các biến cục bộ**


* Chúng chỉ tồn tại từ khi một hàm được gọi cho đến khi hàm kết thúc.



**Example:**

function showMessage() { let message = “Temporary message”; console.log(message); }

showMessage(); // console.log(message); // Error: message is not accessible after the function ends

Trong ví dụ này, khi hàm kết thúc, biến `message` bị hủy và không thể được tham chiếu nữa.



### 4.3 Chuỗi phạm vi là gì?



Khi các phạm vi lồng nhau được tạo ra (như các hàm lồng nhau), JavaScript tìm kiếm các biến bằng một cơ chế gọi là **chuỗi phạm vi**.



**Example:**

let outerVar = “Outside”;

function outerFunction() { let innerVar = “Inside”;

function innerFunction() { console.log(outerVar); // Accesses outer scope console.log(innerVar); // Accesses inner scope }

innerFunction(); }

outerFunction();

Trong ví dụ này, `innerFunction` sẽ tra cứu các biến trong phạm vi của nó trước, sau đó trong phạm vi cha, và cuối cùng trong phạm vi toàn cục nếu cần. Quá trình tra cứu này là chuỗi phạm vi.



### 4.4 Hiểu về Closure



Một **closure** là một tính năng mà trong đó một hàm bên trong tiếp tục giữ quyền truy cập vào các biến từ một hàm bên ngoài.



**Example:**

function createCounter() { let count = 0; // Outer variable

return function () { count++; // Accesses outer variable return count; }; }

const counter = createCounter(); counter(); // 1 counter(); // 2

Trong ví dụ này, hàm bên trong tiếp tục truy cập biến bên ngoài `count`, cho phép nó duy trì trạng thái. Closure hữu ích cho các bộ đếm, quản lý cấu hình và nhiều hơn nữa.



### 4.5 Các điểm quan trọng khi sử dụng Phạm vi và Thời gian tồn tại một cách hiệu quả



1. **Giữ số lượng biến toàn cục ở mức tối thiểu**


* Để ngăn ngừa xung đột tên và ghi đè không mong muốn, tránh sử dụng biến toàn cục một cách không cần thiết.


1. **Sử dụng tốt phạm vi cục bộ**


* Quản lý các biến trong hàm hoặc khối giúp ngăn ngừa lỗi không mong muốn.


1. **Ưu tiên const**


* Nếu bạn không cần gán lại, hãy sử dụng `const` để tăng độ an toàn.


1. **Hiểu khi nào closure hữu ích**


* Sử dụng closure một cách chủ động khi bạn cần quản lý trạng thái hoặc đóng gói hàm.







## 5. Khởi tạo biến và Xử lý Undefined

Trong JavaScript, việc khởi tạo biến một cách đúng đắn rất quan trọng. Các biến chưa được khởi tạo và giá trị undefined có thể dẫn đến lỗi không mong muốn, vì vậy bạn cần hiểu hành vi của chúng.



### 5.1 Khởi Tạo Biến Là Gì?



Khởi tạo có nghĩa là gán giá trị đầu tiên cho một biến sau khi khai báo nó.



**Ví dụ:**

let count = 0; // initialized let message; // uninitialized

Trong ví dụ này, `count` được khởi tạo an toàn thành 0. Trong khi đó, `message` không có giá trị nào được gán, điều này có thể gây ra hành vi không mong muốn sau này.



### 5.2 Làm Việc Với Undefined



#### 1. undefined Là Gì?



`undefined` là một giá trị đặc biệt được gán tự động trong các trường hợp sau:



* Các biến chưa được khởi tạo
* Các thuộc tính đối tượng không tồn tại hoặc phần tử mảng
* Các hàm không trả về giá trị



**Ví dụ:**

let value; // uninitialized variable console.log(value); // undefined

let obj = {}; console.log(obj.property); // undefined (property does not exist)

function noReturn() {} console.log(noReturn()); // undefined (no return value)

**Ghi chú:**



* Vì `undefined` thường xảy ra không chủ ý, bạn cần xử lý nó đúng cách trong mã của mình.



#### 2. Cách Kiểm Tra undefined



Đây là các cách an toàn để kiểm tra xem một biến hoặc thuộc tính có phải là undefined hay không.



**Ví dụ:**

let data;

// Method 1: typeof operator if (typeof data === “undefined”) { console.log(“The variable is undefined”); }

// Method 2: strict comparison if (data === undefined) { console.log(“The variable is undefined”); }

Sử dụng `typeof` an toàn hơn vì nó sẽ không ném lỗi ngay cả khi biến chưa được khai báo.



### 5.3 Làm Việc Với null



#### 1. null Là Gì?



`null` đại diện cho một giá trị “rỗng có chủ ý”. Không giống như `undefined`, nó được thiết lập thủ công bởi nhà phát triển.



**Ví dụ:**

let value = null; console.log(value); // null

#### 2. Sự Khác Biệt Giữa undefined và null


Featureundefinednull
MeaningNot defined (automatically set by the system)Intentionally empty (set by the developer)
Typeundefinedobject (a historical design mistake, but still the spec)
Comparisonundefined == null is trueStrict comparison undefined === null is false
**Ví dụ:**

console.log(undefined == null); // true console.log(undefined === null); // false

**Ghi chú:**



* Sử dụng `null` để chỉ rõ ràng một “giá trị rỗng.”
* Phân biệt nó với `undefined` làm rõ ý định của bạn trong mã.



### 5.4 Các Thực Hành Tốt Nhất Cho Khởi Tạo



#### 1. Luôn khởi tạo



Gán một giá trị tại thời điểm khai báo để tránh trạng thái undefined.



**Ví dụ:**

let count = 0; // initialized let message = “”; // initialized with an empty string

#### 2. Sử dụng null để làm rõ ý định



Nếu dữ liệu chưa được xác định, khởi tạo với `null` để chỉ ra rằng bạn dự định thiết lập nó sau.



**Ví dụ:**

let result = null; // will be assigned later

#### 3. Kiểm tra xem các giá trị có được khởi tạo không



Kiểm tra xem các đối số hàm hoặc giá trị trả về có phải là undefined không.



**Ví dụ:**

function greet(name) { if (name === undefined || name === null) { console.log(“No name provided”); } else { console.log(Hello, ${name}!); } }

greet(); // No name provided greet(“Taro”); // Hello, Taro!

### 5.5 Các Lỗi Thường Gặp Và Cách Sửa Chúng



#### 1. ReferenceError



**Nguyên nhân:** Truy cập một biến chưa được khai báo.  
**Ví dụ:**

console.log(name); // Error: name is not defined

**Sửa:**  
Khai báo và khởi tạo biến trước khi sử dụng nó.



#### 2. TypeError



**Nguyên nhân:** Cố gắng truy cập một thuộc tính trên `null` hoặc `undefined`.  
**Ví dụ:**

let obj = null; console.log(obj.property); // Error: cannot read properties

**Sửa:**  
Kiểm tra giá trị trước đó.

if (obj !== null && obj !== undefined) { console.log(obj.property); }

### 5.6 Tóm Tắt



Khởi tạo biến và xử lý giá trị undefined là các kỹ năng cơ bản của JavaScript. Bằng cách khởi tạo đúng cách và thực hiện các kiểm tra an toàn, bạn có thể ngăn chặn các lỗi không mong muốn.



## 6. Quy Tắc Đặt Tên Biến Và Các Thực Hành Tốt Nhất

Trong JavaScript, cách bạn đặt tên biến có tác động đáng kể đến khả năng đọc và bảo trì mã. Bằng cách tuân theo các quy ước đặt tên đúng đắn, ý định của mã trở nên rõ ràng hơn và lỗi dễ tránh hơn. Phần này giải thích chi tiết các quy tắc và thực hành tốt nhất về đặt tên biến.



### 6.1 Các Quy Tắc Cơ Bản Cho Tên Biến



Trong JavaScript, tên biến phải tuân theo các quy tắc này.



#### 1. Các Ký Tự Được Cho Phép



* Chữ cái bảng chữ cái ( `a–z` , `A–Z` )
* Số ( `0–9` )
* Dấu gạch dưới ( `_` )
* Dấu đô la ( `$` )



#### 2. Các Mẫu Không Được Phép



* Tên biến không thể bắt đầu bằng số. **Ví dụ:**

let 1name = “Error”; // Error let name1 = “Correct”;

* Các từ khóa dành riêng của JavaScript không thể sử dụng (ví dụ, `let` , `const` , `class` ). **Ví dụ:**

let const = “Error”; // Error let value = “Correct”;

* Khoảng trắng và ký tự đặc biệt không được phép. **Ví dụ:**

let user name = “Error”; // Error let userName = “Correct”;

### 6.2 Các Kiểu Đặt Tên Phổ Biến



Có một số kiểu đặt tên phổ biến được sử dụng trong JavaScript.



#### 1. camelCase (Khuyến nghị)



Từ đầu tiên bắt đầu bằng chữ cái thường, và các từ tiếp theo bắt đầu bằng chữ cái hoa.



**Ví dụ:**

let userName = “Taro”; // Recommended let totalAmount = 500; // Recommended

#### 2. snake\_case (Sử dụng Hạn chế)



Các từ được phân cách bằng dấu gạch dưới (`_`). Kiểu này thường được sử dụng cho hằng số hoặc trong mã liên quan đến cơ sở dữ liệu.



**Ví dụ:**

let user_name = “Taro”; // Allowed but not common in JavaScript

#### 3. PascalCase (Cho Lớp và Hàm Tạo)



Mỗi từ bắt đầu bằng chữ cái hoa. Thường được sử dụng cho tên lớp và hàm tạo.



**Ví dụ:**

class UserProfile { constructor(name) { this.name = name; } }

#### 4. UPPER\_SNAKE\_CASE cho Hằng Số



Hằng số thường được viết bằng chữ cái hoa với dấu gạch dưới.



**Ví dụ:**

const MAX_VALUE = 100; const DEFAULT_TIMEOUT = 5000;

### 6.3 Thực Hành Tốt Nhất



#### 1. Sử Dụng Tên Ý Nghĩa



Tên biến nên mô tả rõ ràng mục đích của chúng.



**Ví dụ xấu:**

let x = 10; // Meaning unclear

**Ví dụ tốt:**

let itemCount = 10; // Clearly represents the number of items

#### 2. Tránh Viết Tắt Quá Mức



Viết tắt quá mức làm giảm khả năng đọc.



**Ví dụ xấu:**

let nm = “Taro”; // Unclear

**Ví dụ tốt:**

let userName = “Taro”; // Clear intent

#### 3. Duy Trì Tính Nhất Quán



Sử dụng cùng một quy ước đặt tên xuyên suốt mã của bạn.



**Ví dụ xấu:**

let user_name = “Taro”; // snake_case let userAge = 25; // camelCase (inconsistent)

**Ví dụ tốt:**

let userName = “Taro”; let userAge = 25; // Consistent camelCase

#### 4. Sử Dụng Tên Logic Cho Cờ Boolean



Biến boolean nên mô tả một điều kiện hoặc trạng thái.



**Ví dụ xấu:**

let flag = true; // Ambiguous

**Ví dụ tốt:**

let isLoggedIn = true; // Clearly represents state

#### 5. Làm Rõ Số và Đơn Vị



Khi biến đại diện cho giá trị số hoặc đơn vị, hãy làm rõ điều đó.



**Ví dụ xấu:**

let size = 10; // Unit unclear

**Ví dụ tốt:**

let fontSizePx = 10; // Font size in pixels

### 6.4 Hướng Dẫn và Ghi Chú Về Đặt Tên



1. **Sử dụng tiếng Anh**  Lập trình sử dụng tiếng Anh làm ngôn ngữ chuẩn. Tránh sử dụng tiếng Nhật hoặc tên biến phiên âm.



**Ví dụ xấu:**

let namae = “Taro”; // Avoid romanized Japanese

**Ví dụ tốt:**

let userName = “Taro”; // Use English

2. **Sử dụng tiền tố và hậu tố khi hữu ích**  Thêm tiền tố hoặc hậu tố có thể làm rõ vai trò của biến.



**Ví dụ:**

let btnSubmit = document.getElementById(“submit”); // Button element let arrUsers = [“Taro”, “Hanako”]; // Array






## 7. Các Lỗi Phổ Biến và Cách Khắc Phục Chúng

.Trong JavaScript, các lỗi liên quan đến khai báo và sử dụng biến xảy ra thường xuyên. Những lỗi này có thể dừng việc thực thi mã hoặc gây ra hành vi không mong muốn. Phần này giải thích các lỗi phổ biến và cách xử lý chúng.



### 7.1 ReferenceError



#### Cause



Một **ReferenceError** xảy ra khi bạn cố gắng truy cập một biến không tồn tại hoặc nằm ngoài phạm vi của nó.



**Example: Accessing an undeclared variable**

console.log(value); // Error: value is not defined

#### How to Fix



1. Khai báo biến trước khi sử dụng chúng.

let value = 10; console.log(value); // 10

2. Kiểm tra phạm vi của biến.

function test() { let localVar = “Local variable”; } // console.log(localVar); // Error: out of scope

### 7.2 TypeError



#### Cause



Một **TypeError** xảy ra khi một giá trị không phải là kiểu dự kiến.



**Example: Accessing a property of undefined**

let obj; console.log(obj.property); // Error: Cannot read properties of undefined

#### How to Fix



1. Kiểm tra việc khởi tạo và kiểu dữ liệu trước.

let obj = {}; console.log(obj.property); // undefined (no error)

2. Sử dụng toán tử optional chaining ( `?.` ).

let obj; console.log(obj?.property); // undefined (no error)

### 7.3 SyntaxError



#### Cause



Một **SyntaxError** xảy ra khi có lỗi ngữ pháp trong mã.



**Example: Missing semicolon**

let x = 10 let y = 20;

#### How to Fix



1. Sử dụng trình soạn thảo mã hoặc công cụ lint (ví dụ: ESLint) để phát hiện các vấn đề về cú pháp.  
2. Chạy mã của bạn và kiểm tra thông báo lỗi trong công cụ phát triển của trình duyệt hoặc Node.js.



### 7.4 Uncaught Error



#### Cause



Một **Uncaught Error** xuất hiện khi một ngoại lệ được ném ra mà không được xử lý bằng `try...catch`.



**Example:**

throw new Error(“Something went wrong!”);

#### How to Fix



1. Thêm xử lý ngoại lệ.

try { throw new Error(“Error occurred!”); } catch (error) { console.log(error.message); // Error occurred! }

2. Ghi lại thông báo lỗi một cách thích hợp để việc gỡ lỗi dễ dàng hơn.



### 7.5 RangeError



#### Cause



Một **RangeError** xảy ra khi một giá trị nằm ngoài phạm vi cho phép.



**Example 1: Array index out of range**

let arr = [1, 2, 3]; console.log(arr[5]); // undefined (not an error, but unintended)

**Example 2: Invalid array length**

new Array(-1); // Error: Invalid array length

#### How to Fix



1. Kiểm tra chỉ số trước khi truy cập mảng.

let arr = [1, 2, 3]; if (arr[5] !== undefined) { console.log(arr[5]); } else { console.log(“Out of range”); }

2. Kiểm soát điều kiện vòng lặp và độ dài mảng một cách thích hợp.



### 7.6 Other Common Errors



#### 1. NaN



**Cause:** Xảy ra khi một phép toán số học cho ra kết quả không phải là số.  
**Example:**

let result = parseInt(“abc”); // NaN

#### How to Fix



* Sử dụng `isNaN()` để kiểm tra.

if (isNaN(result)) { console.log(“Invalid number”); }

#### 2. Infinity



**Cause:** Xảy ra khi chia cho zero hoặc thực hiện các phép tính cực kỳ lớn.  
**Example:**

let value = 1 / 0; // Infinity

#### How to Fix



* Xác thực giá trị trước khi thực hiện các phép tính.

let value = 10; if (value !== 0) { console.log(100 / value); } else { console.log(“Cannot divide by zero”); }

### 7.7 Summary



Lỗi là điều không thể tránh khỏi trong phát triển JavaScript, nhưng bằng cách hiểu nguyên nhân của chúng và áp dụng các kỹ thuật xử lý phù hợp, bạn có thể giữ cho chương trình của mình ổn định. Dự đoán các khu vực dễ xảy ra lỗi và triển khai xử lý lỗi thích hợp là cần thiết để có mã đáng tin cậy.



## 8. Practical Examples: Programs Using JavaScript Variables



Trong phần này, chúng ta áp dụng những gì đã học về biến JavaScript bằng cách xây dựng các ví dụ chương trình cụ thể. Chúng ta sẽ đi qua từng bước, từ các trường hợp đơn giản đến những trường hợp hơi phức tạp hơn.



### 8.1 Example 1: A Calculation Application



#### Problem:

Tạo một chương trình lưu trữ giá và số lượng của sản phẩm trong các biến, sau đó tính toán và hiển thị tổng chi phí.



#### Code Example:

const pricePerItem = 500; // price per item (constant) let quantity = 3; // quantity (variable) let totalPrice = pricePerItem * quantity; // calculate total

console.log(The total price is ${totalPrice} yen.);

#### Explanation:



1. Hằng số `pricePerItem` đại diện cho giá của mặt hàng, không thay đổi.
2. Biến `quantity` lưu trữ số lượng mặt hàng và có thể được cập nhật.
3. Kết quả tính toán được lưu trữ trong `totalPrice` và hiển thị bằng cách sử dụng template literal.



### 8.2 Example 2: Discount Calculation with Conditional Logic



#### Problem:



Tạo một chương trình áp dụng giảm giá dựa trên tổng số tiền mua hàng.



#### Code Example:

let totalAmount = 1200; // total purchase amount let discount = 0; // discount rate (initialized)

if (totalAmount >= 1000) { discount = 0.1; // 10% discount } else if (totalAmount >= 500) { discount = 0.05; // 5% discount }

let discountedAmount = totalAmount – totalAmount * discount; console.log(The discounted price is ${discountedAmount} yen.);

#### Explanation:



1. Khởi tạo `discount` để tránh lỗi ngay cả khi không có điều kiện nào khớp.
2. Tỷ lệ giảm giá được xác định bằng cách sử dụng các câu lệnh điều kiện.
3. Sử dụng biến giúp dễ dàng sửa đổi điều kiện hoặc giá trị.



### 8.3 Example 3: Data Management with Arrays and Loops



#### Problem:



Quản lý danh sách sản phẩm và giá của chúng bằng cách sử dụng mảng, sau đó tính toán tổng chi phí.



#### Code Example:

const items = [“Apple”, “Banana”, “Orange”]; // item names const prices = [100, 200, 150]; // prices let totalCost = 0; // total cost

for (let i = 0; i < items.length; i++) { console.log(${items[i]}: ${prices[i]} yen); totalCost += prices[i]; }

console.log(Total cost: ${totalCost} yen);

#### Explanation:



1. Mảng cho phép quản lý nhiều điểm dữ liệu liên quan một cách hiệu quả.
2. Vòng lặp xử lý từng mặt hàng mà không cần sao chép mã.
3. Biến `totalCost` tích lũy tổng số.



### 8.4 Example 4: Reusable Calculations with Functions



#### Problem:



Tạo một hàm có thể tái sử dụng để tính thuế.



#### Code Example:

function calculateTax(price, taxRate = 0.1) { return price + price * taxRate; }

let itemPrice = 1000; // item price let finalPrice = calculateTax(itemPrice); // price including tax console.log(Price with tax: ${finalPrice} yen);

#### Explanation:



1. Hàm `calculateTax` trả về giá bao gồm thuế.
2. Tham số mặc định cho phép hàm hoạt động mà không cần chỉ định tỷ lệ thuế.
3. Các hàm có thể tái sử dụng cải thiện khả năng bảo trì và hiệu quả.



### 8.5 Example 5: Handling User Input



#### Problem:



Tạo một chương trình hỏi tên và tuổi của người dùng, sau đó xác định xem họ có phải là người lớn hay không.



#### Code Example:

let userName = prompt(“Please enter your name:”); let age = parseInt(prompt(“Please enter your age:”), 10);

if (age >= 18) { console.log(${userName} is an adult.); } else { console.log(${userName} is a minor.); }

#### Explanation:



1. `prompt` được sử dụng để thu thập đầu vào từ người dùng.
2. `parseInt` chuyển đổi đầu vào chuỗi thành số.
3. Tên biến rõ ràng giúp mã dễ hiểu hơn.



### 8.6 Summary



Trong phần này, chúng ta đã khám phá các ví dụ thực tế sử dụng biến JavaScript.



**Key takeaways:**



1. **Ứng dụng tính toán:** Thực hiện phép toán cơ bản và quản lý biến.
2. **Giảm giá có điều kiện:** Thay đổi giá trị động dựa trên điều kiện.
3. **Mảng và vòng lặp:** Quản lý và xử lý nhiều điểm dữ liệu một cách hiệu quả.
4. **Hàm:** Cải thiện khả năng tái sử dụng và bảo trì.
5. **Đầu vào người dùng:** Xây dựng các chương trình tương tác bằng cách sử dụng biến.







## 9. Câu hỏi thường gặp (FAQ)

.

Phần này trả lời các câu hỏi thường gặp về biến trong JavaScript, bao gồm những bẫy cho người mới bắt đầu và các vấn đề nâng cao hơn.

### Q1: Tôi nên dùng var, let hay const?

#### A:

Trong hầu hết các trường hợp, hãy dùng **const** làm mặc định.

* Nó ngăn việc gán lại và khai báo lại, làm cho mã an toàn hơn.  
* Nó thể hiện rõ ý định rằng giá trị không nên thay đổi.

Chỉ dùng **let** khi cần thiết phải gán lại.

Tránh **var** trong JavaScript hiện đại vì nó bỏ qua phạm vi khối và có thể gây ra lỗi không mong muốn.

### Q2: Tôi có cần khai báo kiểu biến trong JavaScript không?

#### A:

Không. JavaScript là một **ngôn ngữ động (dynamically typed)**, vì vậy kiểu biến được xác định tự động dựa trên giá trị được gán.

**Ví dụ:**

let value = 10; // number value = “string”; // string (no error)

Tuy nhiên, kiểu động có thể gây ra các lỗi không mong muốn, vì vậy hãy cẩn thận. Sử dụng TypeScript có thể cải thiện độ an toàn về kiểu.

### Q3: Tôi có thể sửa đổi các thuộc tính của đối tượng được khai báo bằng const không?

#### A:

Có. **const** ngăn việc gán lại chính biến, nhưng các thuộc tính của đối tượng vẫn có thể được sửa đổi.

**Ví dụ:**

const user = { name: “Alice” }; user.name = “Bob”; // property update allowed console.log(user);

// user = {}; // Error: reassignment not allowed

### Q4: Sự khác nhau giữa undefined và null là gì?

#### A:

* **undefined:** Biến đã được khai báo nhưng chưa được gán giá trị.  
* **null:** Giá trị “trống” được gán một cách rõ ràng.

**Ví dụ:**

let a; // undefined let b = null; // explicitly empty

### Q5: Tại sao nên tránh sử dụng biến toàn cục?

#### A:

Biến toàn cục có thể gây ra một số vấn đề:

1. **Xung đột tên:** Nguy cơ cao hơn về việc trùng tên.  
2. **Khó bảo trì:** Khó theo dõi nơi giá trị bị thay đổi.  
3. **Khó gỡ lỗi:** Giá trị có thể bị ghi đè một cách bất ngờ.

**Giải pháp:**  
Nếu thực sự cần, hãy nhóm các biến toàn cục vào một đối tượng namespace.

**Ví dụ:**

const App = { userName: “Alice”, userAge: 25 };

console.log(App.userName);

### Q6: Tôi nên sử dụng quy tắc đặt tên nào?

#### A:

Các quy tắc được khuyến nghị bao gồm:

1. **camelCase:** Dùng cho biến và hàm.

let userName = “Alice”;

2. **PascalCase:** Dùng cho lớp và constructor.

class UserProfile {}

3. **UPPER_SNAKE_CASE:** Dùng cho hằng số.

const MAX_COUNT = 100;

### Q7: Closure là gì?

#### A:

Closure là một tính năng cho phép một hàm giữ quyền truy cập vào các biến từ phạm vi bên ngoài của nó.

**Ví dụ:**

function counter() { let count = 0;

return function () { count++; return count; }; }

const increment = counter(); console.log(increment()); // 1 console.log(increment()); // 2 “`

Closures hữu ích cho việc quản lý trạng thái và đóng gói (encapsulation).

10. Kết luận

Trong bài viết này, chúng ta đã bao quát toàn diện về biến trong JavaScript, từ các khái niệm cơ bản đến cách sử dụng nâng cao. Biến là nền tảng để quản lý dữ liệu và viết các chương trình linh hoạt, hiệu quả.

10.1 Tóm tắt các điểm chính

1. Kiến thức cơ bản về biến

  • Biến tạm thời lưu trữ dữ liệu để tái sử dụng.
  • Kiểu động mang lại tính linh hoạt nhưng đòi hỏi quản lý cẩn thận.

2. Các phương pháp khai báo

  • var: Phạm vi hàm, có thể khai báo lại, nhưng không được khuyến nghị.
  • let: Phạm vi khối, có thể gán lại.
  • const: Phạm vi khối, là lựa chọn an toàn nhất cho hầu hết các trường hợp.

3. Phạm vi và vòng đời

  • Phạm vi xác định nơi biến có thể được truy cập.
  • Giảm thiểu biến toàn cục và tận dụng phạm vi cục bộ/khối.

4. Khởi tạo và xử lý undefined

  • undefined: Tự động được gán khi không có giá trị nào được đặt.
  • null: Đại diện rõ ràng cho một giá trị trống.

5. Đặt tên và các thực hành tốt

  • Sử dụng tên có ý nghĩa, nhất quán (ưu tiên camelCase).
  • Dùng UPPER_SNAKE_CASE cho hằng số.

6. Các lỗi thường gặp

  • Hiểu các lỗi phổ biến (ReferenceError, TypeError, …) giúp cải thiện hiệu quả gỡ lỗi.
  • Xử lý lỗi đúng cách tăng độ ổn định của chương trình.

7. Các Ví Dụ Mã Thực Tế

  • Các ví dụ thực hành minh họa các phép tính, điều kiện, mảng, hàm và đầu vào người dùng.

10.2 Các Bước Tiếp Theo

1. Chuyển Sang Các Chủ Đề Nâng Cao

  • Hàm và phương thức: Cải thiện tính mô-đun và tái sử dụng.
  • Đối tượng và lớp: Làm việc với các cấu trúc dữ liệu phức tạp.
  • Các tính năng hiện đại ES6+: Chuỗi mẫu, hàm mũi tên, phân rã, và hơn thế nữa.

2. Thực Hành Với Các Dự Án Thực Tế

Áp dụng biến trong các dự án thực tế sẽ làm sâu sắc thêm sự hiểu biết của bạn.

Ví dụ:

  • Xây dựng một ứng dụng ToDo đơn giản.
  • Tạo một công cụ máy tính hoặc lịch.
  • Triển khai xác thực biểu mẫu.

10.3 Những Suy Nghĩ Cuối Cùng

Các biến JavaScript là một khối xây dựng cốt lõi của lập trình. Bằng cách khai báo và quản lý chúng đúng cách, bạn có thể viết mã an toàn, hiệu quả và dễ bảo trì.

Với kiến thức có cấu trúc thu được từ bài viết này—từ cơ bản đến sử dụng nâng cao—bạn đã được chuẩn bị tốt để tiếp tục thực hành và củng cố kỹ năng JavaScript của mình thông qua mã hóa thực hành.

広告