Khái niệm
Symbol (ES2015) là kiểu dữ liệu nguyên thủy (primitive) duy nhất, bất biến, và hoàn toàn unique. Dùng làm key cho object property để tránh xung đột tên, đặc biệt khi mở rộng thư viện/third-party code.
Đặc điểm
- Tạo bằng
Symbol()(không dùngnew) - Mỗi lần gọi
Symbol()tạo giá trị khác nhau - Không tự động chuyển đổi sang string
- Không xuất hiện trong
for...in,Object.keys(),JSON.stringify()
Ví dụ cơ bản
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Symbols</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
.result { font-size: 16px; color: #6a1b9a; font-weight: 500; margin: 20px 0; padding: 15px; background: #f3e5f5; border-radius: 4px; min-height: 100px; white-space: pre-wrap; }
button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<h1>Symbol trong JavaScript</h1>
<div class="result" id="result"></div>
<button id="btn">HIỂN THỊ & SO SÁNH SYMBOL</button>
<h3>Nhấn nút để hiển thị và so sánh Symbol</h3>
<script>
const btnEle = document.getElementById('btn');
const resEle = document.getElementById('result');
// Tạo Symbol
const sym1 = Symbol('test');
const sym2 = Symbol('test');
const sym3 = Symbol.for('shared'); // Global symbol registry
const sym4 = Symbol.for('shared'); // Cùng key -> cùng Symbol
btnEle.addEventListener('click', () => {
resEle.textContent = '';
// Hiển thị Symbol
resEle.textContent += `sym1: ${sym1.toString()}\n`;
resEle.textContent += `sym2: ${sym2.toString()}\n`;
resEle.textContent += `sym3 (for): ${sym3.toString()}\n`;
resEle.textContent += `sym4 (for): ${sym4.toString()}\n\n`;
// So sánh
resEle.textContent += `sym1 === sym2: ${sym1 === sym2}\n`; // false - unique
resEle.textContent += `sym3 === sym4: ${sym3 === sym4}\n`; // true - global registry
// Dùng làm key object
const obj = {
[sym1]: 'Giá trị riêng',
[Symbol('id')]: 123,
name: 'Public'
};
resEle.textContent += `\nObject keys: ${Object.keys(obj)}`; // Chỉ ['name']
resEle.textContent += `\nOwnPropertySymbols: ${Object.getOwnPropertySymbols(obj).map(s => s.toString())}`;
resEle.textContent += `\nobj[sym1]: ${obj[sym1]}`;
});
</script>
</body>
</html>
Kết quả
sym1: Symbol(test) sym2: Symbol(test) sym3 (for): Symbol(for shared) sym4 (for): Symbol(for shared) sym1 === sym2: false sym3 === sym4: true Object keys: name OwnPropertySymbols: Symbol(test), Symbol(id) obj[sym1]: Giá trị riêng
Symbol nổi tiếng (Well-known Symbols)
JS định nghĩa sẵn các Symbol để tùy chỉnh hành vi built-in:
| Symbol | Mục đích |
|---|---|
Symbol.iterator | Làm object iterable (dùng cho for...of) |
Symbol.toPrimitive | Tùy chỉnh chuyển đổi sang primitive |
Symbol.toStringTag | Tùy chỉnh Object.prototype.toString() |
Symbol.hasInstance | Tùy chỉnh instanceof |
Symbol.asyncIterator | Async iterable (for await...of) |
Ví dụ: Custom Iterator
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
let current = this.from;
return {
next() {
return current <= this.to
? { value: current++, done: false }
: { done: true };
}
};
}
};
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}