From dd2d3f7049478a4a56a0d6ac77e2d5430e649cb6 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Fri, 3 Mar 2023 08:38:39 +0700 Subject: [PATCH 1/5] Update article.md --- 1-js/04-object-basics/08-symbol/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index 626eedb53..72cdfdc71 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -1,5 +1,5 @@ -# Symbol type +# Kiểu ký tự By specification, object property keys may be either of string type, or of symbol type. Not numbers, not booleans, only strings or symbols, these two types. From a9f2f1a3c86129bbfca9cadab7ade20c42f4a19a Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Fri, 3 Mar 2023 11:17:44 +0700 Subject: [PATCH 2/5] Update article.md --- 1-js/04-object-basics/08-symbol/article.md | 102 ++++++++++----------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index 72cdfdc71..6cfc2ef04 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -1,31 +1,31 @@ # Kiểu ký tự -By specification, object property keys may be either of string type, or of symbol type. Not numbers, not booleans, only strings or symbols, these two types. +Theo thông số kỹ thuật, các khóa thuộc tính đối tượng có thể thuộc loại chuỗi hoặc loại ký hiệu. Không phải số, không phải booleans, chỉ có chuỗi hoặc ký hiệu, hai loại này. -Till now we've been using only strings. Now let's see the benefits that symbols can give us. +Cho đến bây giờ chúng ta chỉ sử dụng các chuỗi. Bây giờ hãy xem những lợi ích mà các ký tự có thể mang lại cho chúng ta. -## Symbols +## Ký tự -A "symbol" represents a unique identifier. +Một "ký tự" đại diện cho một mã định danh duy nhất. -A value of this type can be created using `Symbol()`: +Giá trị của loại này có thể được tạo bằng cách sử dụng `Symbol()`: ```js // id is a new symbol let id = Symbol(); ``` -Upon creation, we can give symbol a description (also called a symbol name), mostly useful for debugging purposes: +Khi tạo, chúng ta có thể cung cấp cho ký tự một mô tả (còn được gọi là tên ký tự), chủ yếu hữu ích cho mục đích gỡ lỗi: ```js -// id is a symbol with the description "id" +// id là một ký tự với mô tả "id" let id = Symbol("id"); ``` -Symbols are guaranteed to be unique. Even if we create many symbols with the same description, they are different values. The description is just a label that doesn't affect anything. +Các ký tự được đảm bảo là duy nhất. Ngay cả khi chúng ta tạo nhiều ký tự có cùng mô tả, chúng vẫn có giá trị khác nhau. Mô tả chỉ là một nhãn không ảnh hưởng gì. -For instance, here are two symbols with the same description -- they are not equal: +Chẳng hạn, đây là hai ký tự có cùng mô tả -- chúng không bằng nhau: ```js run let id1 = Symbol("id"); @@ -36,12 +36,12 @@ alert(id1 == id2); // false */!* ``` -If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. JavaScript symbols are different. +Nếu bạn đã quen thuộc với Ruby hoặc một ngôn ngữ khác cũng có một số loại "ký tự" -- đừng hiểu lầm. Các ký tự JavaScript là khác nhau. -````warn header="Symbols don't auto-convert to a string" -Most values in JavaScript support implicit conversion to a string. For instance, we can `alert` almost any value, and it will work. Symbols are special. They don't auto-convert. +````warn header="Các ký tự không tự động chuyển đổi thành chuỗi" +Hầu hết các giá trị trong JavaScript đều hỗ trợ chuyển đổi ngầm định thành chuỗi. Chẳng hạn, chúng ta có thể `alert` gần như bất kỳ giá trị nào và nó sẽ hoạt động. Ký tự là đặc biệt. Họ không tự động chuyển đổi. -For instance, this `alert` will show an error: +Chẳng hạn, `alert` này sẽ hiển thị lỗi: ```js run let id = Symbol("id"); @@ -50,17 +50,17 @@ alert(id); // TypeError: Cannot convert a Symbol value to a string */!* ``` -That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not accidentally convert one into another. +Đó là "bảo vệ ngôn ngữ" chống lại sự lộn xộn, bởi vì các chuỗi và ký tự về cơ bản là khác nhau và không nên vô tình chuyển đổi cái này thành cái khác. -If we really want to show a symbol, we need to explicitly call `.toString()` on it, like here: +Nếu chúng ta thực sự muốn hiển thị một ký tự, chúng ta cần gọi `.toString()` một cách rõ ràng trên đó, như sau: ```js run let id = Symbol("id"); *!* -alert(id.toString()); // Symbol(id), now it works +alert(id.toString()); // Symbol(id), bây giờ nó hoạt động */!* ``` -Or get `symbol.description` property to show the description only: +Hoặc nhận thuộc tính `symbol.description` để chỉ hiển thị mô tả: ```js run let id = Symbol("id"); *!* @@ -70,16 +70,16 @@ alert(id.description); // id ```` -## "Hidden" properties +## "Thuộc tính ẩn" -Symbols allow us to create "hidden" properties of an object, that no other part of code can accidentally access or overwrite. +Các ký tự cho phép chúng ta tạo các thuộc tính "ẩn" của một đối tượng, mà không phần mã nào khác có thể vô tình truy cập hoặc ghi đè lên. -For instance, if we're working with `user` objects, that belong to a third-party code. We'd like to add identifiers to them. +Chẳng hạn, nếu chúng ta đang làm việc với các đối tượng `user`, thuộc về mã của bên thứ ba. Chúng ta muốn thêm số nhận dạng cho chúng. -Let's use a symbol key for it: +Hãy sử dụng một phím ký tự cho nó: ```js run -let user = { // belongs to another code +let user = { // thuộc một mã khác name: "John" }; @@ -87,16 +87,16 @@ let id = Symbol("id"); user[id] = 1; -alert( user[id] ); // we can access the data using the symbol as the key +alert( user[id] ); // chúng ta có thể truy cập dữ liệu bằng cách lấy ký tự làm khóa ``` -What's the benefit of using `Symbol("id")` over a string `"id"`? +Lợi ích của việc sử dụng `Symbol("id")` trên chuỗi `"id"` là gì? -As `user` objects belongs to another code, and that code also works with them, we shouldn't just add any fields to it. That's unsafe. But a symbol cannot be accessed accidentally, the third-party code probably won't even see it, so it's probably all right to do. +Vì các đối tượng `user` thuộc về một mã khác và mã đó cũng hoạt động với chúng, nên chúng ta không nên chỉ thêm bất kỳ trường nào vào đó. Điều đó không an toàn. Nhưng một ký tự không thể vô tình được truy cập, mã của bên thứ ba thậm chí có thể sẽ không nhìn thấy nó, vì vậy có thể làm như vậy là ổn. -Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes. That may be another JavaScript library, so that the scripts are completely unaware of each other. +Ngoài ra, hãy tưởng tượng rằng một tập lệnh khác muốn có mã định danh riêng bên trong `user`, cho các mục đích riêng của nó. Đó có thể là một thư viện JavaScript khác, do đó các tập lệnh hoàn toàn không biết về nhau. -Then that script can create its own `Symbol("id")`, like this: +Sau đó, tập lệnh đó có thể tạo `Symbol("id")` của riêng nó, như sau: ```js // ... @@ -105,27 +105,27 @@ let id = Symbol("id"); user[id] = "Their id value"; ``` -There will be no conflict between our and their identifiers, because symbols are always different, even if they have the same name. +Sẽ không có xung đột giữa số nhận dạng của chúng ta và của họ, bởi vì các ký tự luôn khác nhau, ngay cả khi chúng có cùng tên. -...But if we used a string `"id"` instead of a symbol for the same purpose, then there *would* be a conflict: +...Nhưng nếu chúng ta sử dụng một chuỗi `"id"` thay vì một ký tự cho cùng một mục đích, thì *sẽ* xảy ra xung đột: ```js let user = { name: "John" }; -// Our script uses "id" property +// Tập lệnh của chúng ta sử dụng thuộc tính "id" user.id = "Our id value"; -// ...Another script also wants "id" for its purposes... +// ...Một tập lệnh khác cũng muốn "id" cho mục đích của nó... user.id = "Their id value" -// Boom! overwritten by another script! +// Bùm! ghi đè bởi một tập lệnh khác! ``` -### Symbols in an object literal +### Các ký hiệu trong một object literal -If we want to use a symbol in an object literal `{...}`, we need square brackets around it. +Nếu chúng ta muốn sử dụng một ký tự trong một object literal `{...}`, thì chúng ta cần có dấu ngoặc vuông xung quanh ký tự đó. -Like this: +Như thế này: ```js let id = Symbol("id"); @@ -133,17 +133,17 @@ let id = Symbol("id"); let user = { name: "John", *!* - [id]: 123 // not "id": 123 + [id]: 123 // không có "id": 123 */!* }; ``` -That's because we need the value from the variable `id` as the key, not the string "id". +Đó là bởi vì chúng ta cần giá trị từ biến `id` làm khóa chứ không phải chuỗi "id". -### Symbols are skipped by for..in +### Các ký tự bị for..in bỏ qua -Symbolic properties do not participate in `for..in` loop. +Các thuộc tính tượng trưng không tham gia vào vòng lặp `for..in`. -For instance: +Ví dụ: ```js run let id = Symbol("id"); @@ -154,16 +154,16 @@ let user = { }; *!* -for (let key in user) alert(key); // name, age (no symbols) +for (let key in user) alert(key); // tên, tuổi (không có ký hiệu) */!* -// the direct access by the symbol works +// truy cập trực tiếp bằng ký tự hoạt động alert( "Direct: " + user[id] ); ``` -`Object.keys(user)` also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. +`Object.keys(user)` cũng bỏ qua chúng. Đó là một phần của nguyên tắc "ẩn các thuộc tính tượng trưng" chung. Nếu một tập lệnh hoặc thư viện khác lặp lại đối tượng của chúng ta, nó sẽ không truy cập bất ngờ vào thuộc tính tượng trưng. -In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties: +Ngược lại, [Object.assign](mdn:js/Object/assign) sao chép cả thuộc tính chuỗi và ký tự: ```js run let id = Symbol("id"); @@ -176,19 +176,19 @@ let clone = Object.assign({}, user); alert( clone[id] ); // 123 ``` -There's no paradox here. That's by design. The idea is that when we clone an object or merge objects, we usually want *all* properties to be copied (including symbols like `id`). +Không có nghịch lý ở đây. Đó là do thiết kế. Ý tưởng là khi chúng ta sao chép một đối tượng hoặc hợp nhất các đối tượng, chúng ta thường muốn sao chép *tất cả* các thuộc tính (bao gồm các ký hiệu như `id`). -## Global symbols +## Ký tự chung -As we've seen, usually all symbols are different, even if they have the same name. But sometimes we want same-named symbols to be same entities. For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property. +Như chúng ta đã thấy, thông thường tất cả các ký tự đều khác nhau, ngay cả khi chúng có cùng tên. Nhưng đôi khi chúng ta muốn các ký tự cùng tên là cùng một thực thể. Chẳng hạn, các phần khác nhau trong ứng dụng của chúng tôi muốn truy cập ký tự `"id"` có nghĩa chính xác là cùng một thuộc tính. -To achieve that, there exists a *global symbol registry*. We can create symbols in it and access them later, and it guarantees that repeated accesses by the same name return exactly the same symbol. +Để đạt được điều đó, tồn tại *cơ quan đăng ký ký tự chung*. Chúng ta có thể tạo các ký tự trong đó và truy cập chúng sau này, đồng thời đảm bảo rằng các lần truy cập lặp lại cùng tên sẽ trả về chính xác cùng một ký tự. -In order to read (create if absent) a symbol from the registry, use `Symbol.for(key)`. +Để đọc (tạo nếu không có) một ký tự từ sổ đăng ký, hãy sử dụng `Symbol.for(key)`. -That call checks the global registry, and if there's a symbol described as `key`, then returns it, otherwise creates a new symbol `Symbol(key)` and stores it in the registry by the given `key`. +Cuộc gọi đó sẽ kiểm tra sổ đăng ký chung và nếu có một ký tự được mô tả là `key` thì trả về ký tự đó, nếu không thì tạo một ký tự mới `Symbol(key)` và lưu trữ nó trong sổ đăng ký theo `key` đã cho. -For instance: +Ví dụ: ```js run // read from the global registry From 6e66f3e5e96aa02f934bae99484cecd2fe0ae906 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Fri, 3 Mar 2023 11:43:58 +0700 Subject: [PATCH 3/5] Update article.md --- 1-js/04-object-basics/08-symbol/article.md | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index 6cfc2ef04..dafc4ccfe 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -191,87 +191,87 @@ Cuộc gọi đó sẽ kiểm tra sổ đăng ký chung và nếu có một ký Ví dụ: ```js run -// read from the global registry -let id = Symbol.for("id"); // if the symbol did not exist, it is created +// đọc từ sổ đăng ký chung +let id = Symbol.for("id"); // nếu biểu tượng không tồn tại, nó sẽ được tạo ra -// read it again (maybe from another part of the code) +// đọc lại (có thể từ một phần khác của mã) let idAgain = Symbol.for("id"); -// the same symbol +// cùng một ký tự alert( id === idAgain ); // true ``` -Symbols inside the registry are called *global symbols*. If we want an application-wide symbol, accessible everywhere in the code -- that's what they are for. +Các ký tự bên trong sổ đăng ký được gọi là *ký hiệu chung*. Nếu chúng ta muốn một ký tự toàn ứng dụng, có thể truy cập được ở mọi nơi trong mã -- đó là mục đích của chúng. -```smart header="That sounds like Ruby" -In some programming languages, like Ruby, there's a single symbol per name. +```smart header="Nghe giống như Ruby" +Trong một số ngôn ngữ lập trình, như Ruby, có một ký tự duy nhất cho mỗi tên. -In JavaScript, as we can see, that's right for global symbols. +Trong JavaScript, như chúng ta có thể thấy, điều đó phù hợp với các ký tự chung. ``` ### Symbol.keyFor -For global symbols, not only `Symbol.for(key)` returns a symbol by name, but there's a reverse call: `Symbol.keyFor(sym)`, that does the reverse: returns a name by a global symbol. +Đối với các ký tự chung, không chỉ `Symbol.for(key)` trả về một ký tự theo tên, mà còn có một cách gọi ngược lại: `Symbol.keyFor(sym)`, có tác dụng ngược lại: trả về một tên theo một ký tự chung. -For instance: +Ví dụ: ```js run -// get symbol by name +// lấy ký tự theo tên let sym = Symbol.for("name"); let sym2 = Symbol.for("id"); -// get name by symbol -alert( Symbol.keyFor(sym) ); // name +// lấy tên theo ký tự +alert( Symbol.keyFor(sym) ); // tên alert( Symbol.keyFor(sym2) ); // id ``` -The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`. +`Symbol.keyFor` sử dụng nội bộ sổ đăng ký ký tự chung để tra cứu khóa cho ký tự. Vì vậy, nó không hoạt động đối với các ký tự không chung. Nếu ký tự không phải là chung, nó sẽ không thể tìm thấy nó và trả về `undefined`. -That said, any symbols have `description` property. +Điều đó nói rằng, bất kỳ ký tự nào cũng có thuộc tính `mô tả`. -For instance: +Ví dụ: ```js run let globalSymbol = Symbol.for("name"); let localSymbol = Symbol("name"); -alert( Symbol.keyFor(globalSymbol) ); // name, global symbol -alert( Symbol.keyFor(localSymbol) ); // undefined, not global +alert( Symbol.keyFor(globalSymbol) ); // tên, ký tự chung +alert( Symbol.keyFor(localSymbol) ); // undefined, không chung -alert( localSymbol.description ); // name +alert( localSymbol.description ); // tên ``` -## System symbols +## Ký tự hệ thống -There exist many "system" symbols that JavaScript uses internally, and we can use them to fine-tune various aspects of our objects. +Có nhiều ký tự "hệ thống" mà JavaScript sử dụng nội bộ và chúng ta có thể sử dụng chúng để tinh chỉnh các khía cạnh khác nhau của đối tượng. -They are listed in the specification in the [Well-known symbols](https://tc39.github.io/ecma262/#sec-well-known-symbols) table: +Chúng được liệt kê trong thông số kỹ thuật trong bảng [Ký tự nổi tiếng](https://tc39.github.io/ecma262/#sec-well-known-symbols): - `Symbol.hasInstance` - `Symbol.isConcatSpreadable` - `Symbol.iterator` - `Symbol.toPrimitive` -- ...and so on. +- ...v.v. -For instance, `Symbol.toPrimitive` allows us to describe object to primitive conversion. We'll see its use very soon. +Chẳng hạn, `Symbol.toPrimitive` cho phép chúng ta mô tả đối tượng thành chuyển đổi nguyên thủy. Chúng ta sẽ thấy việc sử dụng nó rất sớm. -Other symbols will also become familiar when we study the corresponding language features. +Các ký tự khác cũng sẽ trở nên quen thuộc khi chúng ta nghiên cứu các đặc điểm ngôn ngữ tương ứng. -## Summary +## Tóm tắt -`Symbol` is a primitive type for unique identifiers. +`Symbol` là một loại nguyên thủy cho các mã định danh duy nhất. -Symbols are created with `Symbol()` call with an optional description (name). +Các ký tự được tạo bằng lệnh gọi `Symbol()` với một mô tả (tên) tùy chọn. -Symbols are always different values, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry: `Symbol.for(key)` returns (creates if needed) a global symbol with `key` as the name. Multiple calls of `Symbol.for` with the same `key` return exactly the same symbol. +Các ký tự luôn có các giá trị khác nhau, ngay cả khi chúng có cùng tên. Nếu chúng ta muốn các ký tự cùng tên bằng nhau, thì chúng ta nên sử dụng sổ đăng ký chung: `Symbol.for(key)` trả về (tạo nếu cần) một ký tự chung có tên `key`. Nhiều lệnh gọi `Symbol.for` với cùng một `key` trả về chính xác cùng một ký tự. -Symbols have two main use cases: +Các ký tự có hai trường hợp sử dụng chính: -1. "Hidden" object properties. - If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be accidentally processed together with other properties. Also it won't be accessed directly, because another script does not have our symbol. So the property will be protected from accidental use or overwrite. +1. Thuộc tính đối tượng "ẩn". + Nếu chúng ta muốn thêm một thuộc tính vào một đối tượng "thuộc về" một tập lệnh hoặc thư viện khác, chúng ta có thể tạo một ký tự và sử dụng nó làm khóa thuộc tính. Thuộc tính tượng trưng không xuất hiện trong `for..in`, vì vậy thuộc tính này sẽ không được xử lý ngẫu nhiên cùng với các thuộc tính khác. Ngoài ra, nó sẽ không được truy cập trực tiếp vì một tập lệnh khác không có ký tự của chúng ta. Vì vậy, thuộc tính sẽ được bảo vệ khỏi việc sử dụng ngẫu nhiên hoặc ghi đè lên. - So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties. + Vì vậy, chúng ta có thể "ẩn" một thứ gì đó vào những đối tượng mà chúng ta cần, nhưng những người khác không nên nhìn thấy, bằng cách sử dụng các thuộc tính tượng trưng. -2. There are many system symbols used by JavaScript which are accessible as `Symbol.*`. We can use them to alter some built-in behaviors. For instance, later in the tutorial we'll use `Symbol.iterator` for [iterables](info:iterable), `Symbol.toPrimitive` to setup [object-to-primitive conversion](info:object-toprimitive) and so on. +2. Có nhiều ký tự hệ thống được JavaScript sử dụng có thể truy cập dưới dạng `Symbol.*`. Chúng ta có thể sử dụng chúng để thay đổi một số hành vi tích hợp. Chẳng hạn, ở phần sau của hướng dẫn, chúng ta sẽ sử dụng `Symbol.iterator` cho [iterables](info:iterable), `Symbol.toPrimitive` để thiết lập [chuyển đổi đối tượng thành nguyên thủy](info:object-toprimitive), v.v. TRÊN. -Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden. But most libraries, built-in functions and syntax constructs don't use these methods. +Về mặt kỹ thuật, các ký tự không bị ẩn 100%. Có một phương thức tích hợp [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) cho phép chúng ta lấy tất cả các ký tự. Ngoài ra, có một phương thức có tên [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) trả về các khóa *tất cả* của một đối tượng bao gồm các khóa tượng trưng. Vì vậy, chúng không thực sự ẩn. Nhưng hầu hết các thư viện, hàm dựng sẵn và cấu trúc cú pháp không sử dụng các phương thức này. From 678c304d1d9545dd98c357b8ca88106d83513fcb Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 14 Mar 2023 18:21:12 +0700 Subject: [PATCH 4/5] Update article.md --- 1-js/04-object-basics/08-symbol/article.md | 104 ++++++++++----------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index dafc4ccfe..b2b22d2dc 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -1,31 +1,31 @@ -# Kiểu ký tự +# Kiểu ký hiệu Theo thông số kỹ thuật, các khóa thuộc tính đối tượng có thể thuộc loại chuỗi hoặc loại ký hiệu. Không phải số, không phải booleans, chỉ có chuỗi hoặc ký hiệu, hai loại này. -Cho đến bây giờ chúng ta chỉ sử dụng các chuỗi. Bây giờ hãy xem những lợi ích mà các ký tự có thể mang lại cho chúng ta. +Cho đến bây giờ chúng ta chỉ sử dụng các chuỗi. Bây giờ hãy xem những lợi ích mà các ký hiệu có thể mang lại cho chúng ta. -## Ký tự +## Ký hiệu -Một "ký tự" đại diện cho một mã định danh duy nhất. +Một "ký hiệu" đại diện cho một mã định danh duy nhất. Giá trị của loại này có thể được tạo bằng cách sử dụng `Symbol()`: ```js -// id is a new symbol +// id là một ký hiệu mới let id = Symbol(); ``` -Khi tạo, chúng ta có thể cung cấp cho ký tự một mô tả (còn được gọi là tên ký tự), chủ yếu hữu ích cho mục đích gỡ lỗi: +Khi tạo, chúng ta có thể cung cấp cho ký hiệu một mô tả (còn được gọi là tên ký hiệu), chủ yếu hữu ích cho mục đích gỡ lỗi: ```js -// id là một ký tự với mô tả "id" +// id là một ký hiệu với mô tả "id" let id = Symbol("id"); ``` -Các ký tự được đảm bảo là duy nhất. Ngay cả khi chúng ta tạo nhiều ký tự có cùng mô tả, chúng vẫn có giá trị khác nhau. Mô tả chỉ là một nhãn không ảnh hưởng gì. +Các ký hiệu được đảm bảo là duy nhất. Ngay cả khi chúng ta tạo nhiều ký hiệu có cùng mô tả, chúng vẫn có giá trị khác nhau. Mô tả chỉ là một nhãn không ảnh hưởng gì. -Chẳng hạn, đây là hai ký tự có cùng mô tả -- chúng không bằng nhau: +Chẳng hạn, đây là hai ký hiệu có cùng mô tả -- chúng không bằng nhau: ```js run let id1 = Symbol("id"); @@ -36,23 +36,23 @@ alert(id1 == id2); // false */!* ``` -Nếu bạn đã quen thuộc với Ruby hoặc một ngôn ngữ khác cũng có một số loại "ký tự" -- đừng hiểu lầm. Các ký tự JavaScript là khác nhau. +Nếu bạn đã quen thuộc với Ruby hoặc một ngôn ngữ khác cũng có một số loại "ký hiệu" -- đừng hiểu lầm. Các ký hiệu JavaScript là khác nhau. -````warn header="Các ký tự không tự động chuyển đổi thành chuỗi" -Hầu hết các giá trị trong JavaScript đều hỗ trợ chuyển đổi ngầm định thành chuỗi. Chẳng hạn, chúng ta có thể `alert` gần như bất kỳ giá trị nào và nó sẽ hoạt động. Ký tự là đặc biệt. Họ không tự động chuyển đổi. +````warn header="Các ký hiệu không tự động chuyển đổi thành chuỗi" +Hầu hết các giá trị trong JavaScript đều hỗ trợ chuyển đổi ngầm định thành chuỗi. Chẳng hạn, chúng ta có thể `alert` gần như bất kỳ giá trị nào và nó sẽ hoạt động. Ký hiệu là đặc biệt. Họ không tự động chuyển đổi. Chẳng hạn, `alert` này sẽ hiển thị lỗi: ```js run let id = Symbol("id"); *!* -alert(id); // TypeError: Cannot convert a Symbol value to a string +alert(id); // TypeError: Không thể chuyển đổi giá trị Ký hiệu thành chuỗi */!* ``` Đó là "bảo vệ ngôn ngữ" chống lại sự lộn xộn, bởi vì các chuỗi và ký tự về cơ bản là khác nhau và không nên vô tình chuyển đổi cái này thành cái khác. -Nếu chúng ta thực sự muốn hiển thị một ký tự, chúng ta cần gọi `.toString()` một cách rõ ràng trên đó, như sau: +Nếu chúng ta thực sự muốn hiển thị một ký hiệu, chúng ta cần gọi `.toString()` một cách rõ ràng trên đó, như sau: ```js run let id = Symbol("id"); *!* @@ -72,11 +72,11 @@ alert(id.description); // id ## "Thuộc tính ẩn" -Các ký tự cho phép chúng ta tạo các thuộc tính "ẩn" của một đối tượng, mà không phần mã nào khác có thể vô tình truy cập hoặc ghi đè lên. +Các ký hiệu cho phép chúng ta tạo các thuộc tính "ẩn" của một đối tượng, mà không phần mã nào khác có thể vô tình truy cập hoặc ghi đè lên. Chẳng hạn, nếu chúng ta đang làm việc với các đối tượng `user`, thuộc về mã của bên thứ ba. Chúng ta muốn thêm số nhận dạng cho chúng. -Hãy sử dụng một phím ký tự cho nó: +Hãy sử dụng một phím ký hiệu cho nó: ```js run let user = { // thuộc một mã khác @@ -87,12 +87,12 @@ let id = Symbol("id"); user[id] = 1; -alert( user[id] ); // chúng ta có thể truy cập dữ liệu bằng cách lấy ký tự làm khóa +alert( user[id] ); // chúng ta có thể truy cập dữ liệu bằng cách lấy ký hiệu làm khóa ``` Lợi ích của việc sử dụng `Symbol("id")` trên chuỗi `"id"` là gì? -Vì các đối tượng `user` thuộc về một mã khác và mã đó cũng hoạt động với chúng, nên chúng ta không nên chỉ thêm bất kỳ trường nào vào đó. Điều đó không an toàn. Nhưng một ký tự không thể vô tình được truy cập, mã của bên thứ ba thậm chí có thể sẽ không nhìn thấy nó, vì vậy có thể làm như vậy là ổn. +Vì các đối tượng `user` thuộc về một mã khác và mã đó cũng hoạt động với chúng, nên chúng ta không nên chỉ thêm bất kỳ trường nào vào đó. Điều đó không an toàn. Nhưng một ký hiệu không thể vô tình được truy cập, mã của bên thứ ba thậm chí có thể sẽ không nhìn thấy nó, vì vậy có thể làm như vậy là ổn. Ngoài ra, hãy tưởng tượng rằng một tập lệnh khác muốn có mã định danh riêng bên trong `user`, cho các mục đích riêng của nó. Đó có thể là một thư viện JavaScript khác, do đó các tập lệnh hoàn toàn không biết về nhau. @@ -102,12 +102,12 @@ Sau đó, tập lệnh đó có thể tạo `Symbol("id")` của riêng nó, nh // ... let id = Symbol("id"); -user[id] = "Their id value"; +user[id] = "Giá trị id của họ"; ``` -Sẽ không có xung đột giữa số nhận dạng của chúng ta và của họ, bởi vì các ký tự luôn khác nhau, ngay cả khi chúng có cùng tên. +Sẽ không có xung đột giữa số nhận dạng của chúng ta và của họ, bởi vì các ký hiệu luôn khác nhau, ngay cả khi chúng có cùng tên. -...Nhưng nếu chúng ta sử dụng một chuỗi `"id"` thay vì một ký tự cho cùng một mục đích, thì *sẽ* xảy ra xung đột: +...Nhưng nếu chúng ta sử dụng một chuỗi `"id"` thay vì một ký hiệu cho cùng một mục đích, thì *sẽ* xảy ra xung đột: ```js let user = { name: "John" }; @@ -117,13 +117,13 @@ user.id = "Our id value"; // ...Một tập lệnh khác cũng muốn "id" cho mục đích của nó... -user.id = "Their id value" +user.id = "Giá trị id của họ" // Bùm! ghi đè bởi một tập lệnh khác! ``` ### Các ký hiệu trong một object literal -Nếu chúng ta muốn sử dụng một ký tự trong một object literal `{...}`, thì chúng ta cần có dấu ngoặc vuông xung quanh ký tự đó. +Nếu chúng ta muốn sử dụng một ký hiệu trong một object literal `{...}`, thì chúng ta cần có dấu ngoặc vuông xung quanh ký hiệu đó. Như thế này: @@ -139,7 +139,7 @@ let user = { ``` Đó là bởi vì chúng ta cần giá trị từ biến `id` làm khóa chứ không phải chuỗi "id". -### Các ký tự bị for..in bỏ qua +### Các ký hiệu bị for..in bỏ qua Các thuộc tính tượng trưng không tham gia vào vòng lặp `for..in`. @@ -157,13 +157,13 @@ let user = { for (let key in user) alert(key); // tên, tuổi (không có ký hiệu) */!* -// truy cập trực tiếp bằng ký tự hoạt động +// truy cập trực tiếp bằng ký hiệu hoạt động alert( "Direct: " + user[id] ); ``` `Object.keys(user)` cũng bỏ qua chúng. Đó là một phần của nguyên tắc "ẩn các thuộc tính tượng trưng" chung. Nếu một tập lệnh hoặc thư viện khác lặp lại đối tượng của chúng ta, nó sẽ không truy cập bất ngờ vào thuộc tính tượng trưng. -Ngược lại, [Object.assign](mdn:js/Object/assign) sao chép cả thuộc tính chuỗi và ký tự: +Ngược lại, [Object.assign](mdn:js/Object/assign) sao chép cả thuộc tính chuỗi và ký hiệu: ```js run let id = Symbol("id"); @@ -178,56 +178,56 @@ alert( clone[id] ); // 123 Không có nghịch lý ở đây. Đó là do thiết kế. Ý tưởng là khi chúng ta sao chép một đối tượng hoặc hợp nhất các đối tượng, chúng ta thường muốn sao chép *tất cả* các thuộc tính (bao gồm các ký hiệu như `id`). -## Ký tự chung +## Ký hiệu chung -Như chúng ta đã thấy, thông thường tất cả các ký tự đều khác nhau, ngay cả khi chúng có cùng tên. Nhưng đôi khi chúng ta muốn các ký tự cùng tên là cùng một thực thể. Chẳng hạn, các phần khác nhau trong ứng dụng của chúng tôi muốn truy cập ký tự `"id"` có nghĩa chính xác là cùng một thuộc tính. +Như chúng ta đã thấy, thông thường tất cả các ký hiệu đều khác nhau, ngay cả khi chúng có cùng tên. Nhưng đôi khi chúng ta muốn các ký hiệu cùng tên là cùng một thực thể. Chẳng hạn, các phần khác nhau trong ứng dụng của chúng ta muốn truy cập ký hiệu `"id"` có nghĩa chính xác là cùng một thuộc tính. -Để đạt được điều đó, tồn tại *cơ quan đăng ký ký tự chung*. Chúng ta có thể tạo các ký tự trong đó và truy cập chúng sau này, đồng thời đảm bảo rằng các lần truy cập lặp lại cùng tên sẽ trả về chính xác cùng một ký tự. +Để đạt được điều đó, tồn tại *cơ quan đăng ký ký hiệu chung*. Chúng ta có thể tạo các ký hiệu trong đó và truy cập chúng sau này, đồng thời đảm bảo rằng các lần truy cập lặp lại cùng tên sẽ trả về chính xác cùng một ký hiệu. -Để đọc (tạo nếu không có) một ký tự từ sổ đăng ký, hãy sử dụng `Symbol.for(key)`. +Để đọc (tạo nếu không có) một ký hiệu từ sổ đăng ký, hãy sử dụng `Symbol.for(key)`. -Cuộc gọi đó sẽ kiểm tra sổ đăng ký chung và nếu có một ký tự được mô tả là `key` thì trả về ký tự đó, nếu không thì tạo một ký tự mới `Symbol(key)` và lưu trữ nó trong sổ đăng ký theo `key` đã cho. +Cuộc gọi đó sẽ kiểm tra sổ đăng ký chung và nếu có một ký hiệu được mô tả là `key` thì trả về ký hiệu đó, nếu không thì tạo một ký hiệu mới `Symbol(key)` và lưu trữ nó trong sổ đăng ký theo `key` đã cho. Ví dụ: ```js run // đọc từ sổ đăng ký chung -let id = Symbol.for("id"); // nếu biểu tượng không tồn tại, nó sẽ được tạo ra +let id = Symbol.for("id"); // nếu ký hiệu không tồn tại, nó sẽ được tạo ra // đọc lại (có thể từ một phần khác của mã) let idAgain = Symbol.for("id"); -// cùng một ký tự +// cùng một ký hiệu alert( id === idAgain ); // true ``` -Các ký tự bên trong sổ đăng ký được gọi là *ký hiệu chung*. Nếu chúng ta muốn một ký tự toàn ứng dụng, có thể truy cập được ở mọi nơi trong mã -- đó là mục đích của chúng. +Các ký hiệu bên trong sổ đăng ký được gọi là *ký hiệu chung*. Nếu chúng ta muốn một ký hiệu toàn ứng dụng, có thể truy cập được ở mọi nơi trong mã -- đó là mục đích của chúng. ```smart header="Nghe giống như Ruby" -Trong một số ngôn ngữ lập trình, như Ruby, có một ký tự duy nhất cho mỗi tên. +Trong một số ngôn ngữ lập trình, như Ruby, có một ký hiệu duy nhất cho mỗi tên. -Trong JavaScript, như chúng ta có thể thấy, điều đó phù hợp với các ký tự chung. +Trong JavaScript, như chúng ta có thể thấy, điều đó phù hợp với các ký hiệu chung. ``` ### Symbol.keyFor -Đối với các ký tự chung, không chỉ `Symbol.for(key)` trả về một ký tự theo tên, mà còn có một cách gọi ngược lại: `Symbol.keyFor(sym)`, có tác dụng ngược lại: trả về một tên theo một ký tự chung. +Đối với các ký hiệu chung, không chỉ `Symbol.for(key)` trả về một ký hiệu theo tên, mà còn có một cách gọi ngược lại: `Symbol.keyFor(sym)`, có tác dụng ngược lại: trả về một tên theo một ký hiệu chung. Ví dụ: ```js run -// lấy ký tự theo tên +// lấy ký hiệu theo tên let sym = Symbol.for("name"); let sym2 = Symbol.for("id"); -// lấy tên theo ký tự +// lấy tên theo ký hiệu alert( Symbol.keyFor(sym) ); // tên alert( Symbol.keyFor(sym2) ); // id ``` -`Symbol.keyFor` sử dụng nội bộ sổ đăng ký ký tự chung để tra cứu khóa cho ký tự. Vì vậy, nó không hoạt động đối với các ký tự không chung. Nếu ký tự không phải là chung, nó sẽ không thể tìm thấy nó và trả về `undefined`. +`Symbol.keyFor` sử dụng nội bộ sổ đăng ký ký hiệu chung để tra cứu khóa cho ký hiệu. Vì vậy, nó không hoạt động đối với các ký hiệu không chung. Nếu ký hiệu không phải là chung, nó sẽ không thể tìm thấy nó và trả về `undefined`. -Điều đó nói rằng, bất kỳ ký tự nào cũng có thuộc tính `mô tả`. +Điều đó nói rằng, bất kỳ ký hiệu nào cũng có thuộc tính `mô tả`. Ví dụ: @@ -235,17 +235,17 @@ Ví dụ: let globalSymbol = Symbol.for("name"); let localSymbol = Symbol("name"); -alert( Symbol.keyFor(globalSymbol) ); // tên, ký tự chung +alert( Symbol.keyFor(globalSymbol) ); // tên, ký hiệu chung alert( Symbol.keyFor(localSymbol) ); // undefined, không chung alert( localSymbol.description ); // tên ``` -## Ký tự hệ thống +## Ký hiệu hệ thống -Có nhiều ký tự "hệ thống" mà JavaScript sử dụng nội bộ và chúng ta có thể sử dụng chúng để tinh chỉnh các khía cạnh khác nhau của đối tượng. +Có nhiều ký hiệu "hệ thống" mà JavaScript sử dụng nội bộ và chúng ta có thể sử dụng chúng để tinh chỉnh các khía cạnh khác nhau của đối tượng. -Chúng được liệt kê trong thông số kỹ thuật trong bảng [Ký tự nổi tiếng](https://tc39.github.io/ecma262/#sec-well-known-symbols): +Chúng được liệt kê trong thông số kỹ thuật trong bảng [Ký hiệu nổi tiếng](https://tc39.github.io/ecma262/#sec-well-known-symbols): - `Symbol.hasInstance` - `Symbol.isConcatSpreadable` @@ -255,23 +255,23 @@ Chúng được liệt kê trong thông số kỹ thuật trong bảng [Ký tự Chẳng hạn, `Symbol.toPrimitive` cho phép chúng ta mô tả đối tượng thành chuyển đổi nguyên thủy. Chúng ta sẽ thấy việc sử dụng nó rất sớm. -Các ký tự khác cũng sẽ trở nên quen thuộc khi chúng ta nghiên cứu các đặc điểm ngôn ngữ tương ứng. +Các ký hiệu khác cũng sẽ trở nên quen thuộc khi chúng ta nghiên cứu các đặc điểm ngôn ngữ tương ứng. ## Tóm tắt `Symbol` là một loại nguyên thủy cho các mã định danh duy nhất. -Các ký tự được tạo bằng lệnh gọi `Symbol()` với một mô tả (tên) tùy chọn. +Các ký hiệu được tạo bằng lệnh gọi `Symbol()` với một mô tả (tên) tùy chọn. -Các ký tự luôn có các giá trị khác nhau, ngay cả khi chúng có cùng tên. Nếu chúng ta muốn các ký tự cùng tên bằng nhau, thì chúng ta nên sử dụng sổ đăng ký chung: `Symbol.for(key)` trả về (tạo nếu cần) một ký tự chung có tên `key`. Nhiều lệnh gọi `Symbol.for` với cùng một `key` trả về chính xác cùng một ký tự. +Các ký hiệu luôn có các giá trị khác nhau, ngay cả khi chúng có cùng tên. Nếu chúng ta muốn các ký hiệu cùng tên bằng nhau, thì chúng ta nên sử dụng sổ đăng ký chung: `Symbol.for(key)` trả về (tạo nếu cần) một ký hiệu chung có tên `key`. Nhiều lệnh gọi `Symbol.for` với cùng một `key` trả về chính xác cùng một ký hiệu. -Các ký tự có hai trường hợp sử dụng chính: +Các ký hiệu có hai trường hợp sử dụng chính: 1. Thuộc tính đối tượng "ẩn". - Nếu chúng ta muốn thêm một thuộc tính vào một đối tượng "thuộc về" một tập lệnh hoặc thư viện khác, chúng ta có thể tạo một ký tự và sử dụng nó làm khóa thuộc tính. Thuộc tính tượng trưng không xuất hiện trong `for..in`, vì vậy thuộc tính này sẽ không được xử lý ngẫu nhiên cùng với các thuộc tính khác. Ngoài ra, nó sẽ không được truy cập trực tiếp vì một tập lệnh khác không có ký tự của chúng ta. Vì vậy, thuộc tính sẽ được bảo vệ khỏi việc sử dụng ngẫu nhiên hoặc ghi đè lên. + Nếu chúng ta muốn thêm một thuộc tính vào một đối tượng "thuộc về" một tập lệnh hoặc thư viện khác, chúng ta có thể tạo một ký hiệu và sử dụng nó làm khóa thuộc tính. Thuộc tính tượng trưng không xuất hiện trong `for..in`, vì vậy thuộc tính này sẽ không được xử lý ngẫu nhiên cùng với các thuộc tính khác. Ngoài ra, nó sẽ không được truy cập trực tiếp vì một tập lệnh khác không có ký hiệu của chúng ta. Vì vậy, thuộc tính sẽ được bảo vệ khỏi việc sử dụng ngẫu nhiên hoặc ghi đè lên. Vì vậy, chúng ta có thể "ẩn" một thứ gì đó vào những đối tượng mà chúng ta cần, nhưng những người khác không nên nhìn thấy, bằng cách sử dụng các thuộc tính tượng trưng. -2. Có nhiều ký tự hệ thống được JavaScript sử dụng có thể truy cập dưới dạng `Symbol.*`. Chúng ta có thể sử dụng chúng để thay đổi một số hành vi tích hợp. Chẳng hạn, ở phần sau của hướng dẫn, chúng ta sẽ sử dụng `Symbol.iterator` cho [iterables](info:iterable), `Symbol.toPrimitive` để thiết lập [chuyển đổi đối tượng thành nguyên thủy](info:object-toprimitive), v.v. TRÊN. +2. Có nhiều ký hiệu hệ thống được JavaScript sử dụng có thể truy cập dưới dạng `Symbol.*`. Chúng ta có thể sử dụng chúng để thay đổi một số hành vi tích hợp. Chẳng hạn, ở phần sau của hướng dẫn, chúng ta sẽ sử dụng `Symbol.iterator` cho [iterables](info:iterable), `Symbol.toPrimitive` để thiết lập [chuyển đổi đối tượng thành nguyên thủy](info:object-toprimitive), v.v. -Về mặt kỹ thuật, các ký tự không bị ẩn 100%. Có một phương thức tích hợp [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) cho phép chúng ta lấy tất cả các ký tự. Ngoài ra, có một phương thức có tên [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) trả về các khóa *tất cả* của một đối tượng bao gồm các khóa tượng trưng. Vì vậy, chúng không thực sự ẩn. Nhưng hầu hết các thư viện, hàm dựng sẵn và cấu trúc cú pháp không sử dụng các phương thức này. +Về mặt kỹ thuật, các ký hiệu không bị ẩn 100%. Có một phương thức tích hợp [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) cho phép chúng ta lấy tất cả các ký hiệu. Ngoài ra, có một phương thức có tên [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) trả về các khóa *tất cả* của một đối tượng bao gồm các khóa tượng trưng. Vì vậy, chúng không thực sự bị ẩn. Nhưng hầu hết các thư viện, hàm dựng sẵn và cấu trúc cú pháp không sử dụng các phương thức này. From fa0fc498274a52ac484d06f93453f4485a586dc1 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Wed, 7 Jun 2023 20:22:21 +0700 Subject: [PATCH 5/5] Update article.md --- 1-js/04-object-basics/08-symbol/article.md | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index b2b22d2dc..7ab3eabbc 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -1,13 +1,13 @@ # Kiểu ký hiệu -Theo thông số kỹ thuật, các khóa thuộc tính đối tượng có thể thuộc loại chuỗi hoặc loại ký hiệu. Không phải số, không phải booleans, chỉ có chuỗi hoặc ký hiệu, hai loại này. +Theo thông số kỹ thuật, các khóa thuộc tính đối tượng có thể thuộc loại chuỗi hoặc loại ký hiệu. Không phải số, không phải boolean, chỉ có chuỗi hoặc ký hiệu, hai loại này. Cho đến bây giờ chúng ta chỉ sử dụng các chuỗi. Bây giờ hãy xem những lợi ích mà các ký hiệu có thể mang lại cho chúng ta. ## Ký hiệu -Một "ký hiệu" đại diện cho một mã định danh duy nhất. +Một "ký hiệu" đại diện cho một định danh duy nhất. Giá trị của loại này có thể được tạo bằng cách sử dụng `Symbol()`: @@ -39,14 +39,14 @@ alert(id1 == id2); // false Nếu bạn đã quen thuộc với Ruby hoặc một ngôn ngữ khác cũng có một số loại "ký hiệu" -- đừng hiểu lầm. Các ký hiệu JavaScript là khác nhau. ````warn header="Các ký hiệu không tự động chuyển đổi thành chuỗi" -Hầu hết các giá trị trong JavaScript đều hỗ trợ chuyển đổi ngầm định thành chuỗi. Chẳng hạn, chúng ta có thể `alert` gần như bất kỳ giá trị nào và nó sẽ hoạt động. Ký hiệu là đặc biệt. Họ không tự động chuyển đổi. +Hầu hết các giá trị trong JavaScript đều hỗ trợ chuyển đổi ngầm định thành chuỗi. Chẳng hạn, chúng ta có thể `alert` gần như bất kỳ giá trị nào và nó sẽ hoạt động. Ký hiệu là đặc biệt. Chúng không tự động chuyển đổi. Chẳng hạn, `alert` này sẽ hiển thị lỗi: ```js run let id = Symbol("id"); *!* -alert(id); // TypeError: Không thể chuyển đổi giá trị Ký hiệu thành chuỗi +alert(id); // TypeError: Cannot convert a Symbol value to a string */!* ``` @@ -74,9 +74,9 @@ alert(id.description); // id Các ký hiệu cho phép chúng ta tạo các thuộc tính "ẩn" của một đối tượng, mà không phần mã nào khác có thể vô tình truy cập hoặc ghi đè lên. -Chẳng hạn, nếu chúng ta đang làm việc với các đối tượng `user`, thuộc về mã của bên thứ ba. Chúng ta muốn thêm số nhận dạng cho chúng. +Chẳng hạn, nếu chúng ta đang làm việc với các đối tượng `user`, thuộc về mã của bên thứ ba. Chúng ta muốn thêm định danh cho chúng. -Hãy sử dụng một phím ký hiệu cho nó: +Hãy sử dụng một khoá ký hiệu cho nó: ```js run let user = { // thuộc một mã khác @@ -92,9 +92,9 @@ alert( user[id] ); // chúng ta có thể truy cập dữ liệu bằng cách l Lợi ích của việc sử dụng `Symbol("id")` trên chuỗi `"id"` là gì? -Vì các đối tượng `user` thuộc về một mã khác và mã đó cũng hoạt động với chúng, nên chúng ta không nên chỉ thêm bất kỳ trường nào vào đó. Điều đó không an toàn. Nhưng một ký hiệu không thể vô tình được truy cập, mã của bên thứ ba thậm chí có thể sẽ không nhìn thấy nó, vì vậy có thể làm như vậy là ổn. +Vì các đối tượng `user` thuộc về một mã khác và mã đó cũng hoạt động với chúng, nên chúng ta không nên chỉ thêm bất kỳ lĩnh vực nào vào đó. Điều đó không an toàn. Nhưng một ký hiệu không thể vô tình được truy cập, mã của bên thứ ba thậm chí có thể sẽ không nhìn thấy nó, vì vậy có thể làm như vậy là ổn. -Ngoài ra, hãy tưởng tượng rằng một tập lệnh khác muốn có mã định danh riêng bên trong `user`, cho các mục đích riêng của nó. Đó có thể là một thư viện JavaScript khác, do đó các tập lệnh hoàn toàn không biết về nhau. +Ngoài ra, hãy tưởng tượng rằng một tập lệnh khác muốn có định danh riêng bên trong `user`, cho các mục đích riêng của nó. Đó có thể là một thư viện JavaScript khác, do đó các tập lệnh hoàn toàn không biết về nhau. Sau đó, tập lệnh đó có thể tạo `Symbol("id")` của riêng nó, như sau: @@ -102,10 +102,10 @@ Sau đó, tập lệnh đó có thể tạo `Symbol("id")` của riêng nó, nh // ... let id = Symbol("id"); -user[id] = "Giá trị id của họ"; +user[id] = "Giá trị id của chúng"; ``` -Sẽ không có xung đột giữa số nhận dạng của chúng ta và của họ, bởi vì các ký hiệu luôn khác nhau, ngay cả khi chúng có cùng tên. +Sẽ không có xung đột giữa định danh của chúng ta và của họ, bởi vì các ký hiệu luôn khác nhau, ngay cả khi chúng có cùng tên. ...Nhưng nếu chúng ta sử dụng một chuỗi `"id"` thay vì một ký hiệu cho cùng một mục đích, thì *sẽ* xảy ra xung đột: @@ -182,7 +182,7 @@ Không có nghịch lý ở đây. Đó là do thiết kế. Ý tưởng là khi Như chúng ta đã thấy, thông thường tất cả các ký hiệu đều khác nhau, ngay cả khi chúng có cùng tên. Nhưng đôi khi chúng ta muốn các ký hiệu cùng tên là cùng một thực thể. Chẳng hạn, các phần khác nhau trong ứng dụng của chúng ta muốn truy cập ký hiệu `"id"` có nghĩa chính xác là cùng một thuộc tính. -Để đạt được điều đó, tồn tại *cơ quan đăng ký ký hiệu chung*. Chúng ta có thể tạo các ký hiệu trong đó và truy cập chúng sau này, đồng thời đảm bảo rằng các lần truy cập lặp lại cùng tên sẽ trả về chính xác cùng một ký hiệu. +Để đạt được điều đó, tồn tại *sổ đăng ký ký hiệu chung*. Chúng ta có thể tạo các ký hiệu trong đó và truy cập chúng sau này, đồng thời đảm bảo rằng các lần truy cập lặp lại cùng tên sẽ trả về chính xác cùng một ký hiệu. Để đọc (tạo nếu không có) một ký hiệu từ sổ đăng ký, hãy sử dụng `Symbol.for(key)`. @@ -227,7 +227,7 @@ alert( Symbol.keyFor(sym2) ); // id `Symbol.keyFor` sử dụng nội bộ sổ đăng ký ký hiệu chung để tra cứu khóa cho ký hiệu. Vì vậy, nó không hoạt động đối với các ký hiệu không chung. Nếu ký hiệu không phải là chung, nó sẽ không thể tìm thấy nó và trả về `undefined`. -Điều đó nói rằng, bất kỳ ký hiệu nào cũng có thuộc tính `mô tả`. +Điều đó nói rằng, bất kỳ ký hiệu nào cũng có thuộc tính `description`. Ví dụ: @@ -253,13 +253,13 @@ Chúng được liệt kê trong thông số kỹ thuật trong bảng [Ký hi - `Symbol.toPrimitive` - ...v.v. -Chẳng hạn, `Symbol.toPrimitive` cho phép chúng ta mô tả đối tượng thành chuyển đổi nguyên thủy. Chúng ta sẽ thấy việc sử dụng nó rất sớm. +Chẳng hạn, `Symbol.toPrimitive` cho phép chúng ta mô tả đối tượng thành chuyển đổi nguyên hàm. Chúng ta sẽ thấy việc sử dụng nó rất sớm. Các ký hiệu khác cũng sẽ trở nên quen thuộc khi chúng ta nghiên cứu các đặc điểm ngôn ngữ tương ứng. ## Tóm tắt -`Symbol` là một loại nguyên thủy cho các mã định danh duy nhất. +`Symbol` là một loại nguyên hàm cho các định danh duy nhất. Các ký hiệu được tạo bằng lệnh gọi `Symbol()` với một mô tả (tên) tùy chọn. @@ -272,6 +272,6 @@ Các ký hiệu có hai trường hợp sử dụng chính: Vì vậy, chúng ta có thể "ẩn" một thứ gì đó vào những đối tượng mà chúng ta cần, nhưng những người khác không nên nhìn thấy, bằng cách sử dụng các thuộc tính tượng trưng. -2. Có nhiều ký hiệu hệ thống được JavaScript sử dụng có thể truy cập dưới dạng `Symbol.*`. Chúng ta có thể sử dụng chúng để thay đổi một số hành vi tích hợp. Chẳng hạn, ở phần sau của hướng dẫn, chúng ta sẽ sử dụng `Symbol.iterator` cho [iterables](info:iterable), `Symbol.toPrimitive` để thiết lập [chuyển đổi đối tượng thành nguyên thủy](info:object-toprimitive), v.v. +2. Có nhiều ký hiệu hệ thống được JavaScript sử dụng có thể truy cập dưới dạng `Symbol.*`. Chúng ta có thể sử dụng chúng để thay đổi một số hành vi tích hợp. Chẳng hạn, ở phần sau của hướng dẫn, chúng ta sẽ sử dụng `Symbol.iterator` cho [các iterable](info:iterable), `Symbol.toPrimitive` để thiết lập [chuyển đổi đối tượng thành nguyên thủy](info:object-toprimitive), v.v. -Về mặt kỹ thuật, các ký hiệu không bị ẩn 100%. Có một phương thức tích hợp [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) cho phép chúng ta lấy tất cả các ký hiệu. Ngoài ra, có một phương thức có tên [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) trả về các khóa *tất cả* của một đối tượng bao gồm các khóa tượng trưng. Vì vậy, chúng không thực sự bị ẩn. Nhưng hầu hết các thư viện, hàm dựng sẵn và cấu trúc cú pháp không sử dụng các phương thức này. +Về mặt kỹ thuật, các ký hiệu không bị ẩn 100%. Có một phương thức tích hợp [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) cho phép chúng ta lấy tất cả các ký hiệu. Ngoài ra, có một phương thức có tên [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) trả về *tất cả* các khóa của một đối tượng bao gồm cả khóa tượng trưng. Vì vậy, chúng không thực sự bị ẩn. Nhưng hầu hết các thư viện, hàm dựng sẵn và cấu trúc cú pháp không sử dụng các phương thức này.