Primitive

Bản dịch này chưa hoàn thành. Xin hãy giúp dịch bài viết này từ tiếng Anh

Trong JavaScript, một bản nguyên (giá trị nguyên thủy, giá trị sơ khai, kiểu dữ liệu sơ khai) là dữ liệu mà dữ liệu này không phải object và không có phương thức. Có 7 kiểu dữ liệu bản nguyên: string, number, bigint, boolean, null, undefined, symbol (mới thêm vào trong ECMAScript 2015).

Most of the time, a primitive value is represented directly at the lowest level of the language implementation.

Tất cả bản nguyên đều là bất biến, tức là chúng không thể bị thay đổi. Đừng để bối rối giữa một bản nguyên với một biến được gán giá trị bản nguyên. Biến đó có thể được gán lại giá trị mới, nhưng giá trị đang tồn tại không thể bị thay đổi theo cái cách mà object, mảng và hàm có thể bị thay đổi.

Ví dụ

Ví dụ này sẽ giúp bạn hiểu rõ thực tế là các giá trị bản nguyên không thể bị thay đổi.

JavaScript

 // Sử dụng phương thức chuỗi không làm biến đổi chuỗi
 var bar = "baz";
 console.log(bar);               // baz
 bar.toUpperCase();
 console.log(bar);               // baz

 // Sử dụng một phương thức mảng để làm biến đổi mảng
 var foo = [];
 console.log(foo);               // []
 foo.push("plugh");
 console.log(foo);               // ["plugh"]

 // Câu lệnh gán đã cho bản nguyên một giá trị mới (đây là giá trị mới chứ không phải biến đổi giá trị cũ)
 bar = bar.toUpperCase();       // BAZ

Một bản nguyên có thể bị thay thế, nhưng không thể biến đổi nó trực tiếp.

Ví dụ khác [ Từng-bước ]

Ví dụ sau đây sẽ cho bạn thấy cách JavaScript làm việc với các bản nguyên.

JavaScript

// Xác định bản nguyên
let foo = 5;

// Định nghĩa hàm để thay đổi giá trị bản nguyên
function addTwo(num) {
   num += 2;
}
// Một hàm khác cố gắng làm điều tương tự
function addTwo_v2(foo) {
   foo += 2;
}

// Gọi hàm thứ nhất và truyền bản nguyên của chúng ta vào như là một đối số
addTwo(foo);
// Nhận về giá trị bản nguyên hiện tại
console.log(foo);   // 5

// Cố gắng một lần nữa với hàm thứ hai của chúng ta...
addTwo_v2(foo);
console.log(foo);   // 5

Bạn có đang nghĩ rằng đó phải là 7 chứ không phải 5 không? Nếu có, dưới đây là cách đoạn mã hoạt động:

  • Cả hai lần gọi hàm addTwoaddTwo_v2, JavaScript tra cứu giá trị cho định danh foo. Nó sẽ tìm đích xác biến của chúng ta, cái biến mà đã được thực thể hóa nên với câu lệnh đầu tiên của chúng ta.
  • Sau khi tìm thấy biến ấy rồi, biểu thức gắn với biến sẽ được đánh giá, foo sẽ được thay thế bằng 5 và JavaScript engine sẽ truyền giá trị đó (5) vào hàm như là một đối số.
  • Trước khi thực thi các lệnh trong thân hàm, JavaScript sẽ lấy một bản sao của đối số gốc được truyền vào (cái mà là một bản nguyên) và tạo ra một bản sao có phạm vi local. Các bản sao này, chỉ tồn tại bên trong phạm vi của các hàm, có thể được truy cập thông qua các định danh mà ta đã chỉ định trong câu lệnh khai báo hàm (num cho addTwo, foo cho addTwo_v2)
  • Sau đó, các lệnh trong thân hàm được thực thi:
    • Trong hàm thứ nhất, một biến cục bộ num đã trải qua xong quá trình khởi tạo ở trên. Ta ngay sau đó tăng giá trị của nó thêm 2, không phải giá trị của foo gốc!
    • Trong hàm thứ hai, một biến cục bộ foo đã trải qua xong quá trình khởi tạo ở trên. Ta tăng giá trị của nó thêm 2, không phải giá trị của foo gốc (foo nằm bên ngoài hàm)! Bên cạnh đó, trong trường hợp này, biến foo bên ngoài hàm không thể được truy cập trực tiếp. Đây là bởi vì JavaScript's lexical scoping và the resulting variable shadowing. Biến cục bộ foo che đi biến foo bên ngoài hàm. Để biết thêm chi tiết, xem Closures. (Chú ý rằng window.foo vẫn có thể sử dụng để truy cập vào biến ngoài hàm foo.) 
  • Tóm lại, mọi thay đổi trong hàm sẽ hoàn toàn không ảnh hưởng foo GỐC, bởi ta đang làm việc với bản sao của nó.

Đó là lý do tại sao các Bản nguyên là bất biến - thay vì làm việc trực tiếp với chúng, chúng ta làm việc với bản sao, không làm ảnh hưởng bản gốc.

Các object bọc bản nguyên trong JavaScript

Ngoại trừ nullundefined, mọi giá trị bản nguyên đều có các object tương đương mà các object này sẽ bao bọc xung quanh các giá trị bản nguyên:

  • String cho bản nguyên string.
  • Number cho bản nguyên number.
  • BigInt cho bản nguyên bigint.
  • Boolean cho bản nguyên boolean.
  • Symbol cho bản nguyên symbol.

Phương thức valueOf() của màng bọc sẽ trả về giá trị bản nguyên.

Tham khảo thêm

Hiểu biết chung