Ký hiệu gốc đại diện cho một giá trị duy nhất không bao giờ trùng lặp với bất kỳ giá trị nào khác, bao gồm cả giá trị của các ký hiệu gốc khác. Hai chuỗi gốc được tạo thành từ các ký tự giống hệt nhau sẽ đánh giá là hoàn toàn bằng nhau:
String() === String()
> true
String( "My string." ) === String( "My string." );
> true
Tuy nhiên, không có hai biểu tượng nào được tạo bằng hàm Symbol()
có thể hoàn toàn bằng nhau:
Symbol() === Symbol()
> false
Đặc điểm này cho phép bạn sử dụng các ký hiệu làm khoá thuộc tính duy nhất trong một đối tượng, ngăn chặn các xung đột với khoá mà bất kỳ mã nào khác có thể thêm vào đối tượng đó.
const mySymbol = Symbol( "Desc" );
const myObject = {};
myObject[mySymbol] = "propSymbol";
myObject
> Object { Symbol("Desc"): "propSymbol" }
Có ba loại ký hiệu:
- Các ký hiệu được tạo bằng
Symbol()
- Các biểu tượng dùng chung được đặt và truy xuất từ sổ đăng ký Biểu tượng toàn cục bằng cách sử dụng
Symbol.for()
- "Biểu tượng nổi tiếng" được xác định là thuộc tính tĩnh trên đối tượng Biểu tượng. Các biểu tượng này chứa các phương thức nội bộ không thể bị ghi đè do nhầm lẫn.
Symbol()
chấp nhận nội dung mô tả (hoặc "tên ký hiệu") làm đối số không bắt buộc.
Các nội dung mô tả này là nhãn mà con người có thể đọc được cho mục đích gỡ lỗi và không ảnh hưởng đến tính duy nhất của kết quả. Mọi lệnh gọi đến Symbol
đều trả về một ký hiệu gốc hoàn toàn duy nhất, ngay cả khi nhiều lệnh gọi có nội dung mô tả giống hệt nhau:
Symbol( "My symbol." ) === Symbol( "My symbol." );
> false
Cũng như các loại dữ liệu gốc khác, các ký hiệu kế thừa các phương thức và thuộc tính từ nguyên mẫu của chúng. Ví dụ: bạn có thể truy cập vào nội dung mô tả dưới dạng thuộc tính kế thừa của ký hiệu đã tạo:
let mySymbol = Symbol( "My symbol." );
mySymbol.description
> "My symbol."
Tuy nhiên, bạn không thể tạo biểu tượng bằng từ khoá new
:
let mySymbol = new Symbol();
> Uncaught TypeError: Symbol is not a constructor
Ký hiệu không thể liệt kê được, nghĩa là bạn không thể sử dụng các thuộc tính tượng trưng khi sử dụng các phương thức tiêu chuẩn để lặp lại các thuộc tính đó. Phương thức getOwnPropertySymbols()
cấp quyền truy cập vào các thuộc tính biểu tượng của đối tượng.
Ký hiệu dùng chung
Phương thức Symbol.for()
cố gắng tra cứu mọi ký hiệu hiện có trong sổ đăng ký ký hiệu toàn cục trên toàn thời gian chạy bằng một chuỗi nhất định làm khoá và trả về ký hiệu trùng khớp nếu tìm thấy. Nếu không tìm thấy, trình tạo sẽ tạo một ký hiệu bằng khoá đã chỉ định và thêm ký hiệu đó vào sổ đăng ký toàn cục:
let sharedSymbol = Symbol.for( "My key." );
sharedSymbol === Symbol.for( "My key." )
> true
Các khoá này không có chức năng trùng lặp với nội dung mô tả được chỉ định cho các nguyên hàm Symbol
do tác giả tạo. Để truy cập vào một biểu tượng trong sổ đăng ký biểu tượng, trước tiên, bạn phải tạo biểu tượng đó bằng for()
:
Symbol( "String" ) === Symbol( "String" );
> false
Symbol( "String" ) === Symbol.for( "String" );
> false
Symbol.for( "String" ) === Symbol.for( "String" );
> true
Để truy xuất khoá cho bất kỳ ký hiệu nào từ sổ đăng ký ký hiệu, hãy sử dụng Symbol.keyFor()
:
let mySymbol = Symbol.for( "Key." );
Symbol.keyFor( mySymbol ) ;
> "Key."
Biểu tượng "Nổi tiếng"
Ký hiệu phổ biến là các thuộc tính tĩnh của đối tượng Symbol
, trong đó mỗi thuộc tính là một ký hiệu. Các biểu tượng đã biết cung cấp khoá thuộc tính duy nhất để truy cập và sửa đổi các phương thức tích hợp của JavaScript, đồng thời ngăn hành vi cốt lõi bị ghi đè ngoài ý muốn.
Symbol;
> function Symbol()
asyncIterator: Symbol(Symbol.asyncIterator)
for: function for()
hasInstance: Symbol("Symbol.hasInstance")
isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
iterator: Symbol(Symbol.iterator)
keyFor: function keyFor()
length: 0
match: Symbol("Symbol.match")
matchAll: Symbol("Symbol.matchAll")
name: "Symbol"
prototype: Object { … }
replace: Symbol("Symbol.replace")
search: Symbol("Symbol.search")
species: Symbol("Symbol.species")
split: Symbol("Symbol.split")
toPrimitive: Symbol("Symbol.toPrimitive")
toStringTag: Symbol("Symbol.toStringTag")
unscopables: Symbol("Symbol.unscopables")
<prototype>: function ()
Vì các ký hiệu là một tính năng dành riêng cho ES6, nên các giá trị tượng trưng này được dùng làm "điểm mở rộng" để các nhà phát triển sửa đổi hành vi của JavaScript mà không gây ra vấn đề về khả năng tương thích ngược.
Các giá trị ký hiệu phổ biến thường được tạo kiểu bằng tiền tố @@
hoặc được gói trong %
để phân biệt các khoá với nguyên mẫu có thể thay đổi. Ví dụ: @@match
(hoặc %match%
) là tham chiếu đến Symbol.match
không thể thay đổi, chứ không phải String.prototype.match
.
Kiểm tra mức độ hiểu biết
Bạn có thể sử dụng new
để tạo biểu tượng không?
Câu nào sau đây mô tả các ký hiệu "được biết đến"?