Skip to content

Commit eeaa6e1

Browse files
committed
feat: update translation of symbol
1 parent b3eb916 commit eeaa6e1

File tree

1 file changed

+67
-55
lines changed

1 file changed

+67
-55
lines changed
Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
11

2-
# Symbol 类型
2+
# symbol 类型
33

4-
根据规范,对象的属性键只能是字符串类型或者 Symbol 类型。不是 Number,也不是 Boolean,只有字符串或 Symbol 这两种类型。
4+
根据规范,只有两种原始类型可以用作对象属性键:
55

6-
到目前为止,我们只见过字符串。现在我们来看看 Symbol 能给我们带来什么好处。
6+
- 字符串类型
7+
- symbol 类型
78

8-
## Symbol
9+
否则,如果使用另一种类型,例如数字,它会被自动转换为字符串。所以 `obj[1]``obj["1"]` 相同,而 `obj[true]``obj["true"]` 相同。
910

10-
"Symbol" 值表示唯一的标识符。
11+
到目前为止,我们一直只使用字符串。
12+
13+
现在我们来看看 symbol 能给我们带来什么。
14+
15+
## symbol
16+
17+
"symbol" 值表示唯一的标识符。
1118

1219
可以使用 `Symbol()` 来创建这种类型的值:
1320

1421
```js
15-
// id 是 symbol 的一个实例化对象
1622
let id = Symbol();
1723
```
1824

19-
创建时,我们可以给 Symbol 一个描述(也称为 Symbol 名),这在代码调试时非常有用:
25+
创建时,我们可以给 symbol 一个描述(也称为 symbol 名),这在代码调试时非常有用:
2026

2127
```js
22-
// id 是描述为 "id" 的 Symbol
28+
// id 是描述为 "id" 的 symbol
2329
let id = Symbol("id");
2430
```
2531

26-
Symbol 保证是唯一的。即使我们创建了许多具有相同描述的 Symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。
32+
symbol 保证是唯一的。即使我们创建了许多具有相同描述的 symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。
2733

28-
例如,这里有两个描述相同的 Symbol —— 它们不相等:
34+
例如,这里有两个描述相同的 symbol —— 它们不相等:
2935

3036
```js run
3137
let id1 = Symbol("id");
@@ -36,23 +42,26 @@ alert(id1 == id2); // false
3642
*/!*
3743
```
3844

39-
如果你熟悉 Ruby 或者其他有 "Symbol" 的语言 —— 别被误导。JavaScript 的 Symbol 是不同的。
45+
如果你熟悉 Ruby 或者其他有 "symbol" 的语言 —— 别被误导。JavaScript 的 symbol 是不同的。
46+
47+
所以,总而言之,symbol 是带有可选描述的“原始唯一值”。让我们看看我们可以在哪里使用它们。
4048

41-
````warn header="Symbol 不会被自动转换为字符串"
42-
JavaScript 中的大多数值都支持字符串的隐式转换。例如,我们可以 `alert` 任何值,都可以生效。Symbol 比较特殊,它不会被自动转换。
49+
````warn header="symbol 不会被自动转换为字符串"
50+
JavaScript 中的大多数值都支持字符串的隐式转换。例如,我们可以 `alert` 任何值,都可以生效。symbol 比较特殊,它不会被自动转换。
4351
4452
例如,这个 `alert` 将会提示出错:
4553
4654
```js run
4755
let id = Symbol("id");
4856
*!*
49-
alert(id); // 类型错误:无法将 Symbol 值转换为字符串。
57+
alert(id); // 类型错误:无法将 symbol 值转换为字符串。
5058
*/!*
5159
```
5260
53-
这是一种防止混乱的“语言保护”,因为字符串和 Symbol 有本质上的不同,不应该意外地将它们转换成另一个。
61+
这是一种防止混乱的“语言保护”,因为字符串和 symbol 有本质上的不同,不应该意外地将它们转换成另一个。
62+
63+
如果我们真的想显示一个 symbol,我们需要在它上面调用 `.toString()`,如下所示:
5464
55-
如果我们真的想显示一个 Symbol,我们需要在它上面调用 `.toString()`,如下所示:
5665
```js run
5766
let id = Symbol("id");
5867
*!*
@@ -61,6 +70,7 @@ alert(id.toString()); // Symbol(id),现在它有效了
6170
```
6271
6372
或者获取 `symbol.description` 属性,只显示描述(description):
73+
6474
```js run
6575
let id = Symbol("id");
6676
*!*
@@ -72,11 +82,12 @@ alert(id.description); // id
7282

7383
## “隐藏”属性
7484

75-
Symbol 允许我们创建对象的“隐藏”属性,代码的任何其他部分都不能意外访问或重写这些属性。
85+
86+
symbol 允许我们创建对象的“隐藏”属性,代码的任何其他部分都不能意外访问或重写这些属性。
7687

7788
例如,如果我们使用的是属于第三方代码的 `user` 对象,我们想要给它们添加一些标识符。
7889

79-
我们可以给它们使用 Symbol 键:
90+
我们可以给它们使用 symbol 键:
8091

8192
```js run
8293
let user = { // 属于另一个代码
@@ -87,12 +98,12 @@ let id = Symbol("id");
8798

8899
user[id] = 1;
89100

90-
alert( user[id] ); // 我们可以使用 Symbol 作为键来访问数据
101+
alert( user[id] ); // 我们可以使用 symbol 作为键来访问数据
91102
```
92103

93104
使用 `Symbol("id")` 作为键,比起用字符串 `"id"` 来有什么好处呢?
94105

95-
因为 `user` 对象属于其他的代码,那些代码也会使用这个对象,所以我们不应该在它上面直接添加任何字段,这样很不安全。但是你添加的 Symbol 属性不会被意外访问到,第三方代码根本不会看到它,所以使用 Symbol 基本上不会有问题。
106+
因为 `user` 对象属于其他的代码,那些代码也会使用这个对象,所以我们不应该在它上面直接添加任何字段,这样很不安全。但是你添加的 symbol 属性不会被意外访问到,第三方代码根本不会看到它,所以使用 symbol 基本上不会有问题。
96107

97108
另外,假设另一个脚本希望在 `user` 中有自己的标识符,以实现自己的目的。这可能是另一个 JavaScript 库,因此脚本之间完全不了解彼此。
98109

@@ -105,7 +116,7 @@ let id = Symbol("id");
105116
user[id] = "Their id value";
106117
```
107118

108-
我们的标识符和它们的标识符之间不会有冲突,因为 Symbol 总是不同的,即使它们有相同的名字。
119+
我们的标识符和它们的标识符之间不会有冲突,因为 symbol 总是不同的,即使它们有相同的名字。
109120

110121
……但如果我们处于同样的目的,使用字符串 `"id"` 而不是用 symbol,那么 **就会** 出现冲突:
111122

@@ -121,9 +132,9 @@ user.id = "Their id value"
121132
// 砰!无意中被另一个脚本重写了 id!
122133
```
123134

124-
### 对象字面量中的 Symbol
135+
### 对象字面量中的 symbol
125136

126-
如果我们要在对象字面量 `{...}` 中使用 Symbol,则需要使用方括号把它括起来。
137+
如果我们要在对象字面量 `{...}` 中使用 symbol,则需要使用方括号把它括起来。
127138

128139
就像这样:
129140

@@ -139,9 +150,9 @@ let user = {
139150
```
140151
这是因为我们需要变量 `id` 的值作为键,而不是字符串 "id"。
141152

142-
### Symbol 在 for..in 中会被跳过
153+
### symbol 在 for..in 中会被跳过
143154

144-
Symbol 属性不参与 `for..in` 循环。
155+
symbol 属性不参与 `for..in` 循环。
145156

146157
例如:
147158

@@ -154,10 +165,10 @@ let user = {
154165
};
155166

156167
*!*
157-
for (let key in user) alert(key); // name, age (no symbols)
168+
for (let key in user) alert(key); // name, age(没有 symbol)
158169
*/!*
159170

160-
// 使用 Symbol 任务直接访问
171+
// 使用 symbol 任务直接访问
161172
alert( "Direct: " + user[id] );
162173
```
163174

@@ -176,76 +187,76 @@ let clone = Object.assign({}, user);
176187
alert( clone[id] ); // 123
177188
```
178189

179-
这里并不矛盾,就是这样设计的。这里的想法是当我们克隆或者合并一个 object 时,通常希望 **所有** 属性被复制(包括像 `id` 这样的 Symbol)。
190+
这里并不矛盾,就是这样设计的。这里的想法是当我们克隆或者合并一个 object 时,通常希望 **所有** 属性被复制(包括像 `id` 这样的 symbol)。
180191

181192
## 全局 symbol
182193

183-
正如我们所看到的,通常所有的 Symbol 都是不同的,即使它们有相同的名字。但有时我们想要名字相同的 Symbol 具有相同的实体。例如,应用程序的不同部分想要访问的 Symbol `"id"` 指的是完全相同的属性。
194+
正如我们所看到的,通常所有的 symbol 都是不同的,即使它们有相同的名字。但有时我们想要名字相同的 symbol 具有相同的实体。例如,应用程序的不同部分想要访问的 symbol `"id"` 指的是完全相同的属性。
184195

185-
为了实现这一点,这里有一个 **全局 Symbol 注册表**。我们可以在其中创建 Symbol 并在稍后访问它们,它可以确保每次访问相同名字的 Symbol 时,返回的都是相同的 Symbol
196+
为了实现这一点,这里有一个 **全局 symbol 注册表**。我们可以在其中创建 symbol 并在稍后访问它们,它可以确保每次访问相同名字的 symbol 时,返回的都是相同的 symbol
186197

187-
要从注册表中读取(不存在则创建)Symbol,请使用 `Symbol.for(key)`
198+
要从注册表中读取(不存在则创建)symbol,请使用 `Symbol.for(key)`
188199

189-
该调用会检查全局注册表,如果有一个描述为 `key`Symbol,则返回该 Symbol,否则将创建一个新 Symbol`Symbol(key)`),并通过给定的 `key` 将其存储在注册表中。
200+
该调用会检查全局注册表,如果有一个描述为 `key`symbol,则返回该 symbol,否则将创建一个新 symbol`Symbol(key)`),并通过给定的 `key` 将其存储在注册表中。
190201

191202
例如:
192203

193204
```js run
194205
// 从全局注册表中读取
195-
let id = Symbol.for("id"); // 如果该 Symbol 不存在,则创建它
206+
let id = Symbol.for("id"); // 如果该 symbol 不存在,则创建它
196207

197208
// 再次读取(可能是在代码中的另一个位置)
198209
let idAgain = Symbol.for("id");
199210

200-
// 相同的 Symbol
211+
// 相同的 symbol
201212
alert( id === idAgain ); // true
202213
```
203214

204-
注册表内的 Symbol 被称为 **全局 Symbol**。如果我们想要一个应用程序范围内的 Symbol,可以在代码中随处访问 —— 这就是它们的用途。
215+
注册表内的 symbol 被称为 **全局 symbol**。如果我们想要一个应用程序范围内的 symbol,可以在代码中随处访问 —— 这就是它们的用途。
205216

206217
```smart header="这听起来像 Ruby"
207-
在一些编程语言中,例如 Ruby,每个名字都有一个 Symbol
218+
在一些编程语言中,例如 Ruby,每个名字都有一个 symbol
208219
209-
正如我们所看到的,在 JavaScript 中,全局 Symbol 也是这样的。
220+
正如我们所看到的,在 JavaScript 中,全局 symbol 也是这样的。
210221
```
211222

212223
### Symbol.keyFor
213224

214-
对于全局 Symbol,不仅有 `Symbol.for(key)` 按名字返回一个 Symbol,还有一个反向调用:`Symbol.keyFor(sym)`,它的作用完全反过来:通过全局 Symbol 返回一个名字。
225+
对于全局 symbol,不仅有 `Symbol.for(key)` 按名字返回一个 symbol,还有一个反向调用:`Symbol.keyFor(sym)`,它的作用完全反过来:通过全局 symbol 返回一个名字。
215226

216227
例如:
217228

218229
```js run
219-
// 通过 name 获取 Symbol
230+
// 通过 name 获取 symbol
220231
let sym = Symbol.for("name");
221232
let sym2 = Symbol.for("id");
222233

223-
// 通过 Symbol 获取 name
234+
// 通过 symbol 获取 name
224235
alert( Symbol.keyFor(sym) ); // name
225236
alert( Symbol.keyFor(sym2) ); // id
226237
```
227238

228-
`Symbol.keyFor` 内部使用全局 Symbol 注册表来查找 Symbol 的键。所以它不适用于非全局 Symbol。如果 Symbol 不是全局的,它将无法找到它并返回 `undefined`
239+
`Symbol.keyFor` 内部使用全局 symbol 注册表来查找 symbol 的键。所以它不适用于非全局 symbol。如果 symbol 不是全局的,它将无法找到它并返回 `undefined`
229240

230-
也就是说,任何 Symbol 都具有 `description` 属性。
241+
也就是说,任何 symbol 都具有 `description` 属性。
231242

232243
例如:
233244

234245
```js run
235246
let globalSymbol = Symbol.for("name");
236247
let localSymbol = Symbol("name");
237248

238-
alert( Symbol.keyFor(globalSymbol) ); // name,全局 Symbol
249+
alert( Symbol.keyFor(globalSymbol) ); // name,全局 symbol
239250
alert( Symbol.keyFor(localSymbol) ); // undefined,非全局
240251

241252
alert( localSymbol.description ); // name
242253
```
243254

244-
## 系统 Symbol
255+
## 系统 symbol
245256

246-
JavaScript 内部有很多“系统” Symbol,我们可以使用它们来微调对象的各个方面。
257+
JavaScript 内部有很多“系统” symbol,我们可以使用它们来微调对象的各个方面。
247258

248-
它们都被列在了 [众所周知的 Symbol](https://tc39.github.io/ecma262/#sec-well-known-symbols) 表的规范中:
259+
它们都被列在了 [众所周知的 symbol](https://tc39.github.io/ecma262/#sec-well-known-symbols) 表的规范中:
249260

250261
- `Symbol.hasInstance`
251262
- `Symbol.isConcatSpreadable`
@@ -255,23 +266,24 @@ JavaScript 内部有很多“系统” Symbol,我们可以使用它们来微
255266

256267
例如,`Symbol.toPrimitive` 允许我们将对象描述为原始值转换。我们很快就会看到它的使用。
257268

258-
当我们研究相应的语言特征时,我们对其他的 Symbol 也会慢慢熟悉起来。
269+
当我们研究相应的语言特征时,我们对其他的 symbol 也会慢慢熟悉起来。
259270

260271
## 总结
261272

262-
`Symbol` 是唯一标识符的基本类型
273+
`symbol` 是唯一标识符的基本类型
263274

264-
Symbol 是使用带有可选描述(name)的 `Symbol()` 调用创建的。
275+
symbol 是使用带有可选描述(name)的 `Symbol()` 调用创建的。
265276

266-
Symbol 总是不同的值,即使它们有相同的名字。如果我们希望同名的 Symbol 相等,那么我们应该使用全局注册表:`Symbol.for(key)` 返回(如果需要的话则创建)一个以 `key` 作为名字的全局 Symbol。使用 `Symbol.for` 多次调用 `key` 相同的 Symbol 时,返回的就是同一个 Symbol
277+
symbol 总是不同的值,即使它们有相同的名字。如果我们希望同名的 symbol 相等,那么我们应该使用全局注册表:`Symbol.for(key)` 返回(如果需要的话则创建)一个以 `key` 作为名字的全局 symbol。使用 `Symbol.for` 多次调用 `key` 相同的 symbol 时,返回的就是同一个 symbol
267278

268-
Symbol 有两个主要的使用场景:
279+
symbol 有两个主要的使用场景:
269280

270281
1. “隐藏” 对象属性。
271-
如果我们想要向“属于”另一个脚本或者库的对象添加一个属性,我们可以创建一个 Symbol 并使用它作为属性的键。Symbol 属性不会出现在 `for..in` 中,因此它不会意外地被与其他属性一起处理。并且,它不会被直接访问,因为另一个脚本没有我们的 symbol。因此,该属性将受到保护,防止被意外使用或重写。
272282

273-
因此我们可以使用 Symbol 属性“秘密地”将一些东西隐藏到我们需要的对象中,但其他地方看不到它。
283+
如果我们想要向“属于”另一个脚本或者库的对象添加一个属性,我们可以创建一个 symbol 并使用它作为属性的键。symbol 属性不会出现在 `for..in` 中,因此它不会意外地被与其他属性一起处理。并且,它不会被直接访问,因为另一个脚本没有我们的 symbol。因此,该属性将受到保护,防止被意外使用或重写。
284+
285+
因此我们可以使用 symbol 属性“秘密地”将一些东西隐藏到我们需要的对象中,但其他地方看不到它。
274286

275-
2. JavaScript 使用了许多系统 Symbol,这些 Symbol 可以作为 `Symbol.*` 访问。我们可以使用它们来改变一些内建行为。例如,在本教程的后面部分,我们将使用 `Symbol.iterator` 来进行 [迭代](info:iterable) 操作,使用 `Symbol.toPrimitive` 来设置 [对象原始值的转换](info:object-toprimitive) 等等。
287+
2. JavaScript 使用了许多系统 symbol,这些 symbol 可以作为 `Symbol.*` 访问。我们可以使用它们来改变一些内建行为。例如,在本教程的后面部分,我们将使用 `Symbol.iterator` 来进行 [迭代](info:iterable) 操作,使用 `Symbol.toPrimitive` 来设置 [对象原始值的转换](info:object-toprimitive) 等等。
276288

277-
从技术上说,Symbol 不是 100% 隐藏的。有一个内建方法 [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) 允许我们获取所有的 Symbol。还有一个名为 [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) 的方法可以返回一个对象的 **所有** 键,包括 Symbol。所以它们并不是真正的隐藏。但是大多数库、内建方法和语法结构都没有使用这些方法。
289+
从技术上说,symbol 不是 100% 隐藏的。有一个内建方法 [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) 允许我们获取所有的 symbol。还有一个名为 [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) 的方法可以返回一个对象的 **所有** 键,包括 symbol。所以它们并不是真正的隐藏。但是大多数库、内建方法和语法结构都没有使用这些方法。

0 commit comments

Comments
 (0)