Có bao giờ bạn tự hỏi tại sao khi bạn thay đổi giá trị trong JavaScript nhưng lại không như mong đợi?
Trong bài viết này, chúng ta sẽ cùng tìm hiểu về hai khái niệm quan trọng trong JavaScript: tham chiếu (reference) và tham trị (value). Chúng ta sẽ xem xét cách chúng hoạt động, sự khác biệt giữa chúng, và cách sử dụng chúng đúng cách trong code của bạn.
1. Tham trị là gì?
Trong JavaScript, các giá trị nguyên thủy như số (number), chuỗi (string), boolean, null, và undefined được gọi là giá trị tham trị (pass by value). Điều này có nghĩa là khi bạn gán một biến với một giá trị nguyên thủy, giá trị này sẽ được sao chép và bất kỳ thay đổi nào đối với giá trị mới sẽ không ảnh hưởng đến giá trị ban đầu.
Ví dụ:
let a = 5;
let b = a;
b = 10;
console.log(a); // Kết quả: 5
console.log(b); // Kết quả: 10
Trong ví dụ trên, a
và b
là hai biến độc lập nhau mặc dù chúng có cùng giá trị ban đầu. Khi thay đổi giá trị của b
, a
không bị ảnh hưởng.
2. Tham chiếu là gì?
Ngược lại với tham trị, tham chiếu áp dụng cho các đối tượng như object, array, và function. Khi bạn gán một biến với một đối tượng, biến đó sẽ lưu trữ một tham chiếu đến đối tượng trong bộ nhớ. Điều này có nghĩa là nếu bạn thay đổi đối tượng qua một biến, mọi biến khác tham chiếu đến đối tượng đó sẽ thấy sự thay đổi này.
Ví dụ:
let obj1 = { name: 'John' };
let obj2 = obj1;
obj2.name = 'Jane';
console.log(obj1.name); // Kết quả: Jane
console.log(obj2.name); // Kết quả: Jane
Trong ví dụ trên, obj1
và obj2
cùng tham chiếu đến cùng một đối tượng. Vì vậy, khi bạn thay đổi thuộc tính name
của obj2
, thuộc tính name
của obj1
cũng thay đổi.
3. Sự khác biệt giữa tham chiếu và tham trị
Để hiểu rõ hơn sự khác biệt giữa tham chiếu và tham trị, hãy xem bảng so sánh dưới đây:
Tham trị (Pass by Value) | Tham chiếu (Pass by Reference) | |
Kiểu dữ liệu | Số, chuỗi, boolean, null, undefined | Đối tượng, mảng, hàm |
Cách gán giá trị | Sao chép giá trị thực tế | Sao chép tham chiếu (địa chỉ) của đối tượng |
Ảnh hưởng của thay đổi | Thay đổi biến không ảnh hưởng đến biến gốc | Thay đổi đối tượng ảnh hưởng đến tất cả các biến tham chiếu |
Sao chép giá trị | Tạo một bản sao độc lập | Tạo một liên kết đến cùng một đối tượng |
Tối ưu bộ nhớ | Không, mỗi biến giữ một giá trị riêng | Có, nhiều biến có thể tham chiếu cùng một đối tượng |
4. Các trường hợp sử dụng trong thực tế
Sử dụng tham trị
Khi bạn cần tạo ra các biến độc lập.
Khi bạn làm việc với các giá trị nguyên thủy và không muốn thay đổi chúng thông qua các biến khác.
Ví dụ:
function increment(num) {
num++;
return num;
}
let value = 5;
let newValue = increment(value);
console.log(value); // Kết quả: 5
console.log(newValue); // Kết quả: 6
Trong ví dụ này, num
là một giá trị nguyên thủy và được truyền theo tham trị. Thay đổi num
bên trong hàm không ảnh hưởng đến value
.
Sử dụng tham chiếu
Khi bạn cần làm việc với các đối tượng và muốn các thay đổi được ảnh hưởng khắp các nơi khác.
Khi bạn muốn tránh việc sao chép các đối tượng lớn để tiết kiệm bộ nhớ.
Ví dụ:
function addProperty(obj) {
obj.newProp = 'new';
}
let myObj = { prop: 'old' };
addProperty(myObj);
console.log(myObj); // Kết quả: { prop: 'old', newProp: 'new' }
Trong ví dụ này, myObj
là một đối tượng và được truyền theo tham chiếu. Thay đổi obj
bên trong hàm sẽ ảnh hưởng đến myObj
.
❗️ Chú ý:
Hiểu rõ khi nào dùng tham chiếu và khi nào dùng tham trị: Việc này sẽ giúp bạn tránh được các lỗi không mong muốn và tối ưu hóa mã nguồn của mình.
Cẩn thận khi làm việc với các đối tượng: Do chúng được truyền theo tham chiếu, hãy chắc chắn rằng các thay đổi là cần thiết và không gây ra lỗi logic.
Sử dụng các kỹ thuật sao chép đối tượng nếu cần: Nếu bạn muốn tạo ra một bản sao của một đối tượng mà không làm ảnh hưởng đến đối tượng gốc, bạn có thể sử dụng các phương pháp như
Object.assign
hoặc các thư viện nhưlodash
.
Hi vọng qua bài viết này, bạn đã có cái nhìn rõ ràng hơn về sự khác biệt giữa tham chiếu và tham trị trong JavaScript. Hiểu rõ hai khái niệm này sẽ giúp bạn viết code hiệu quả hơn và tránh được nhiều lỗi phổ biến.