JavaScript: Giá trị nguyên thủy và giá trị tham chiếu trong Javascript


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

Tổng quan

Trong hướng dẫn này, bạn sẽ tìm hiểu về hai loại giá trị khác nhau trong JavaScript bao gồm giá trị nguyên thủy và giá trị tham chiếu.

JavaScript có hai loại giá trị khác nhau:

  • Giá trị nguyên thủy (Primitive values)
  • Các giá trị tham chiếu (Reference Values)

Giá trị nguyên thủy là các đơn vị dữ liệu nguyên tử trong khi giá trị tham chiếu là các đối tượng có thể bao gồm nhiều giá trị.

Bộ nhớ stack và heap

Khi bạn khai báo các biến , JavaScript engine sẽ phân bổ bộ nhớ cho chúng trên hai vị trí bộ nhớ: stack và heap.

Dữ liệu tĩnh là dữ liệu có kích thước cố định tại thời điểm biên dịch. Dữ liệu tĩnh bao gồm:

  • Các giá trị nguyên thủy ( null , undefined , boolean , number, string, symbol và BigInt )
  • Các giá trị tham chiếu đề cập đến các đối tượng.

Vì dữ liệu tĩnh có kích thước không thay đổi nên JavaScript engine sẽ phân bổ một lượng không gian bộ nhớ cố định cho dữ liệu tĩnh và lưu trữ nó trên stack.
Ví dụ: phần sau đây khai báo hai biến và khởi tạo giá trị của chúng thành một chuỗi ký tự và một số:

let name = 'John';
let age = 25;

Vì name và age là các giá trị nguyên thủy nên JavaScript engine lưu trữ các biến này trên stack như trong hình sau:

Lưu ý rằng chuỗi là đối tượng (object) trong nhiều ngôn ngữ lập trình, bao gồm Java và C#. Tuy nhiên, chuỗi là giá trị nguyên thủy trong JavaScript.

Không giống như stack, JavaScript lưu trữ các đối tượng (và hàm) trên heap. JavaScript engine không phân bổ lượng bộ nhớ cố định cho các đối tượng này. Thay vào đó, nó sẽ phân bổ nhiều không gian hơn khi cần thiết.

Ví dụ sau đây định nghĩa các biến nameage, và person:

let name = 'John';
let age = 25;

let person = {
  name: 'John',
  age: 25,
};

Bên trong, JavaScript engine phân bổ bộ nhớ như trong hình sau:

Thuộc tính động

Giá trị tham chiếu cho phép bạn thêm, thay đổi hoặc xóa thuộc tính bất kỳ lúc nào. Ví dụ:

let person = {
  name: 'John',
  age: 25,
};

// add the ssn property
person.ssn = '123-45-6789';

// change the name
person.name = 'John Doe';

// delete the age property
delete person.age;

console.log(person);

Output:

{ name: 'John Doe', ssn: '123-45-6789' }

Không giống như giá trị tham chiếu, giá trị nguyên thủy không thể có thuộc tính. Điều này có nghĩa là bạn không thể thêm thuộc tính vào giá trị nguyên thủy.

JavaScript cho phép bạn thêm thuộc tính vào giá trị nguyên thủy. Tuy nhiên, nó sẽ không có tác dụng gì. Ví dụ:

let name = 'John';
name.alias = 'Knight';

console.log(name.alias); // undefined

Trong ví dụ này, chúng tôi thêm thuộc tính alias vào name là biến với giá trị nguyên thủy. Nhưng khi chúng ta truy cập thuộc tính alias thông qua name, nó sẽ trả về undefined.

Sao chép giá trị

Khi bạn gán một giá trị nguyên thủy từ biến này sang biến khác, JavaScript engine sẽ tạo một bản sao của giá trị đó và gán nó cho biến đó. Ví dụ:

let age = 25;
let newAge = age;

Trong ví dụ này:

  • Đầu tiên, khai báo một biến age và khởi tạo giá trị của nó bằng 25.
  • Thứ hai, khai báo một biến khác newAge và gán giá trị biến age cho newAge.

Thực tế, JavaScript engine tạo một bản sao của giá trị nguyên thủy 25 và gán nó cho biến newAge.

Hình ảnh sau đây minh họa bộ nhớ ngăn xếp sau khi gán:

Trên bộ nhớ stack, newAge và age là các biến riêng biệt. Nếu bạn thay đổi giá trị của một biến, nó sẽ không ảnh hưởng đến biến kia.

let age = 25;
let newAge = age;

newAge = newAge + 1;
console.log(age, newAge); // 25 26

Khi bạn gán giá trị tham chiếu từ biến này sang biến khác, JavaScript engine sẽ tạo tham chiếu để cả hai biến đều tham chiếu đến cùng một đối tượng trên bộ nhớ heap. Điều này có nghĩa là nếu bạn thay đổi một biến, nó sẽ ảnh hưởng đến biến kia.

let person = {
  name: 'John',
  age: 25,
};

let member = person;

member.age = 26;

console.log(person);
console.log(member);

Giải thích

Đầu tiên, khai báo một biến person và khởi tạo giá trị của nó bằng một đối tượng có hai thuộc tính name và age.

Thứ hai, gán biến person cho biến member. Trong bộ nhớ, cả hai biến đều tham chiếu đến cùng một đối tượng, như trong hình sau:

Thứ ba, thay đổi thuộc tính age của đối tượng thông qua biến member:

Vì cả person và member đều tham chiếu đến cùng một đối tượng nên việc thay đổi đối tượng thông qua biến member cũng được phản ánh trong biến person.

Tổng kết

  • Javascript có hai loại giá trị: giá trị nguyên thủy và giá trị tham chiếu.
  • Bạn có thể thêm, thay đổi hoặc xóa các thuộc tính của giá trị tham chiếu, trong khi bạn không thể làm điều đó với giá trị nguyên thủy.
  • Sao chép một giá trị nguyên thủy từ biến này sang biến khác sẽ tạo ra một bản sao giá trị riêng. Điều đó có nghĩa là việc thay đổi giá trị của một biến sẽ không ảnh hưởng đến biến kia.
  • Sao chép giá trị tham chiếu từ biến này sang biến khác sẽ tạo tham chiếu sao cho hai biến tham chiếu đến cùng một đối tượng. Điều này có nghĩa là việc thay đổi đối tượng thông qua một biến sẽ phản ánh ở một biến khác.
» Tiếp: JavaScript try…catch
« Trước: 20 cách thực hành tốt nhất để cải thiện hiệu suất JavaScript
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!