Symbols là gì? Các kiểu dữ liệu symbol trong JavaScript

Trong JavaScript, symbol là một kiểu dữ liệu đặc biệt và ít được nhắc đến so với các kiểu dữ liệu phổ biến như string, number hay boolean. Tuy nhiên, symbols đóng vai trò quan trọng trong việc tạo ra các thuộc tính duy nhất cho đối tượng, giúp ngăn chặn xung đột tên và cung cấp tính bảo mật cho mã nguồn. Bài viết này sẽ giải thích symbols là gì, các tính năng của symbol và cách sử dụng symbols hiệu quả trong JavaScript.

Symbols là gì?

Symbols là một kiểu dữ liệu nguyên thủy (primitive) trong JavaScript, được giới thiệu trong ECMAScript 2015 (ES6). Symbol tạo ra một giá trị duy nhất và bất biến, thường được sử dụng để định danh duy nhất các thuộc tính của đối tượng. Symbol không thể bị thay đổi hoặc lặp lại, đảm bảo rằng mỗi symbol là duy nhất và không thể trùng lặp với bất kỳ giá trị nào khác.

Symbols là một kiểu dữ liệu nguyên thủy (primitive) trong JavaScript
Symbols là một kiểu dữ liệu nguyên thủy (primitive) trong JavaScript

Cú pháp của symbol

Bạn có thể tạo một symbol bằng cách sử dụng hàm Symbol() như sau:

let mySymbol = Symbol();

Mỗi lần gọi Symbol(), một giá trị symbol mới sẽ được tạo ra và giá trị này là duy nhất. Ngay cả khi bạn tạo hai symbols với cùng mô tả, chúng vẫn sẽ là hai giá trị khác nhau:

let symbol1 = Symbol(‘description’);
let symbol2 = Symbol(‘description’);
console.log(symbol1 === symbol2); // false

Tính năng và lợi ích của symbol trong JavaScript

Symbols có những tính năng đặc biệt mà các kiểu dữ liệu khác không có, giúp chúng trở thành một công cụ mạnh mẽ trong JavaScript:

1. Định danh duy nhất

Symbols giúp tạo ra các thuộc tính duy nhất cho đối tượng. Điều này đặc biệt hữu ích trong trường hợp bạn muốn tạo các thuộc tính không xung đột với các thuộc tính khác. Ví dụ:

let person = {
  name: ‘John Doe’
};
let ageSymbol = Symbol(‘age’);
person[ageSymbol] = 30;
console.log(person.age); // undefined
console.log(person[ageSymbol]); // 30

Trong ví dụ trên, thuộc tính age không bị xung đột với bất kỳ thuộc tính nào khác vì nó được định danh bằng một symbol.

Symbols giúp tạo ra các thuộc tính duy nhất cho đối tượng
Symbols giúp tạo ra các thuộc tính duy nhất cho đối tượng

2. Không thể bị ghi đè

Một trong những lợi ích của việc sử dụng symbol là thuộc tính được định danh bởi symbol không thể bị ghi đè hoặc thay đổi từ bên ngoài, giúp bảo mật mã nguồn và giảm thiểu rủi ro xung đột.

3. Bảo mật cho các thuộc tính

Symbols giúp bảo mật các thuộc tính của đối tượng, vì chúng không thể được truy cập thông qua cú pháp thông thường như object.property mà chỉ có thể truy cập bằng cách sử dụng chính symbol đó. Điều này giúp bảo vệ các thuộc tính nội bộ của đối tượng khỏi bị truy cập hoặc thay đổi ngoài ý muốn.

4. Symbol không xuất hiện trong vòng lặp for…in hoặc Object.kets()

Một đặc tính thú vị của symbols là chúng không xuất hiện trong các vòng lặp for…in hoặc khi sử dụng Object.kets() để lấy danh sách các thuộc tính của đối tượng. Điều này giúp giữ cho các thuộc tính được bảo mật hơn khi làm việc với các đối tượng có nhiều thuộc tính.

let obj = {};
let hiddenSymbol = Symbol(‘hidden’);
obj[hiddenSymbol] = ‘Hidden value’;
for (let key in obj) {
  console.log(key); // Không in ra giá trị của hiddenSymbol
}

Các kiểu dữ liệu symbol trong JavaScript

JavaScript không chỉ cung cấp symbol cơ bản mà còn hỗ trợ một số loại symbol đặc biệt được sử dụng cho các mục đích khác nhau trong ngôn ngữ:

1. Symbol.iterator

Symbol.iterator là một symbol đặc biệt được sử dụng để tạo ra các đối tượng có thể lặp qua (iterable) trong JavaScript. Nó thường được sử dụng để tạo ra các iterator cho các cấu trúc dữ liệu tùy chỉnh hoặc để thực hiện tính năng lặp qua đối tượng.

Ví dụ:

let iterableObject = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};
for (let value of iterableObject) {
  console.log(value); // 1, 2, 3
}

2. Symbol.toStringTag

Symbol.toStringTag cho phép bạn tùy chỉnh kết quả của phương thức Object.prototype.toString() khi gọi trên một đối tượng. Điều này có thể hữu ích khi bạn muốn đối tượng của mình trả về một chuỗi tùy chỉnh khi được gọi với toString().

Ví dụ:

let myObject = {
  [Symbol.toStringTag]: ‘MyCustomObject’
};
console.log(Object.prototype.toString.call(myObject)); // [object MyCustomObject]

3. Symbol.toPrimitive

Symbol.toPrimitive được sử dụng để tùy chỉnh cách một đối tượng chuyển đổi sang kiểu dữ liệu nguyên thủy (primitive) như string, number hoặc boolean. Điều này có thể hữu ích khi bạn muốn kiểm soát cách đối tượng của mình chuyển đổi sang các kiểu dữ liệu khác.

Ví dụ:

let myObj = {
  [Symbol.toPrimitive](hint) {
    if (hint === ‘string’) {
      return ‘String value’;
    }
    return 100;
  }
};
console.log(`${myObj}`); // “String value”
console.log(+myObj); // 100
JavaScript không chỉ cung cấp symbol cơ bản
JavaScript không chỉ cung cấp symbol cơ bản

Sử dụng symbol trong thực tế

Symbols được sử dụng rộng rãi trong các thư viện JavaScript và các framework lớn như React hoặc Vue.js để tạo ra các thuộc tính độc đáo và bảo mật. Chúng giúp ngăn chặn sự can thiệp từ bên ngoài vào các thuộc tính nội bộ của đối tượng hoặc lớp.

Ví dụ, trong React, symbols có thể được sử dụng để định nghĩa các phương thức nội bộ mà bạn không muốn bị ghi đè bởi người dùng khi họ mở rộng lớp hoặc đối tượng của bạn.

Kết luận

Symbols là một kiểu dữ liệu mạnh mẽ và độc đáo trong JavaScript, cung cấp cách tạo ra các thuộc tính duy nhất và bảo mật cho đối tượng. Việc hiểu rõ và áp dụng symbols sẽ giúp bạn viết mã linh hoạt và an toàn hơn, đặc biệt khi làm việc với các thư viện hoặc framework lớn.

Bài viết liên quan