Phụ lục

Kế thừa nguyên mẫu

Ngoại trừ nullundefined, mỗi loại dữ liệu gốc đều có một mẫu gốc (prototype), một trình bao bọc đối tượng tương ứng cung cấp các phương thức để xử lý các giá trị. Khi một phương thức hoặc lượt tra cứu thuộc tính được gọi trên một đối tượng gốc, JavaScript sẽ gói đối tượng gốc ở chế độ nền và gọi phương thức hoặc thực hiện lượt tra cứu thuộc tính trên đối tượng trình bao bọc.

Ví dụ: một chuỗi cố định không có phương thức riêng, nhưng bạn có thể gọi phương thức .toUpperCase() trên chuỗi đó nhờ trình bao bọc đối tượng String tương ứng:

"this is a string literal".toUpperCase();
> THIS IS A STRING LITERAL

Đây được gọi là kiểu kế thừa nguyên mẫu – kế thừa các thuộc tính và phương thức từ hàm khởi tạo tương ứng của một giá trị.

Number.prototype
> Number { 0 }
>  constructor: function Number()
>  toExponential: function toExponential()
>  toFixed: function toFixed()
>  toLocaleString: function toLocaleString()
>  toPrecision: function toPrecision()
>  toString: function toString()
>  valueOf: function valueOf()
>  <prototype>: Object {  }

Bạn có thể tạo các dữ liệu gốc bằng các hàm khởi tạo này, thay vì chỉ xác định các dữ liệu đó theo giá trị của chúng. Ví dụ: việc sử dụng hàm khởi tạo String sẽ tạo một đối tượng chuỗi, chứ không phải một chuỗi cố định: một đối tượng không chỉ chứa giá trị chuỗi mà còn chứa tất cả các thuộc tính và phương thức kế thừa của hàm khởi tạo.

const myString = new String( "I'm a string." );

myString;
> String { "I'm a string." }

typeof myString;
> "object"

myString.valueOf();
> "I'm a string."

Trong hầu hết các trường hợp, các đối tượng thu được sẽ hoạt động như các giá trị mà chúng ta đã dùng để xác định các đối tượng đó. Ví dụ: mặc dù việc xác định giá trị số bằng hàm khởi tạo new Number sẽ dẫn đến một đối tượng chứa tất cả phương thức và thuộc tính của nguyên mẫu Number, nhưng bạn có thể sử dụng các toán tử số học trên các đối tượng đó giống như trên số cố định:

const numberOne = new Number(1);
const numberTwo = new Number(2);

numberOne;
> Number { 1 }

typeof numberOne;
> "object"

numberTwo;
> Number { 2 }

typeof numberTwo;
> "object"

numberOne + numberTwo;
> 3

Bạn hiếm khi cần sử dụng các hàm khởi tạo này vì tính năng kế thừa nguyên mẫu tích hợp sẵn của JavaScript có nghĩa là các hàm khởi tạo này không mang lại lợi ích thực tế. Việc tạo các dữ liệu gốc bằng hàm khởi tạo cũng có thể dẫn đến kết quả không mong muốn, vì kết quả là một đối tượng, chứ không phải một giá trị cố định đơn giản:

let stringLiteral = "String literal."

typeof stringLiteral;
> "string"

let stringObject = new String( "String object." );

stringObject
> "object"

Điều này có thể làm phức tạp việc sử dụng các toán tử so sánh nghiêm ngặt:

const myStringLiteral = "My string";
const myStringObject = new String( "My string" );

myStringLiteral === "My string";
> true

myStringObject === "My string";
> false

Tự động chèn dấu chấm phẩy (ASI)