JavaScript符号(Symbols)及其属性深度解析
立即解锁
发布时间: 2025-08-22 01:06:05 阅读量: 2 订阅数: 3 


深入理解ECMAScript 6的核心特性与应用
### JavaScript 符号(Symbols)及其属性深度解析
#### 1. 使用符号(Symbols)
在 JavaScript 里,符号(Symbols)能在任何可使用计算属性名的地方使用。可以在计算对象字面量属性名、`Object.defineProperty()` 和 `Object.defineProperties()` 调用中使用符号。示例代码如下:
```javascript
let firstName = Symbol("first name");
// 使用计算对象字面量属性
let person = {
[firstName]: "Nicholas"
};
// 使属性只读
Object.defineProperty(person, firstName, { writable: false });
let lastName = Symbol("last name");
Object.defineProperties(person, {
[lastName]: {
value: "Zakas",
writable: false
}
});
console.log(person[firstName]); // "Nicholas"
console.log(person[lastName]); // "Zakas"
```
上述代码先利用计算对象字面量属性创建了 `firstName` 符号属性,该属性是非可枚举的,这与使用非符号名称创建的计算属性不同。接着将该属性设为只读,之后使用 `Object.defineProperties()` 方法创建了只读的 `lastName` 符号属性。
#### 2. 识别符号
由于符号是原始值,可使用 `typeof` 运算符来判断变量是否包含符号。在 ECMAScript 6 中,对符号使用 `typeof` 会返回 `"symbol"`。示例如下:
```javascript
let symbol = Symbol("test symbol");
console.log(typeof symbol); // "symbol"
```
虽然有其他间接方法判断变量是否为符号,但 `typeof` 运算符是最准确且首选的技术。
#### 3. 共享符号
有时,代码的不同部分可能需要共享符号。比如,应用程序中有两种不同的对象类型,它们需使用相同的符号属性来表示唯一标识符。在文件或大型代码库中跟踪符号既困难又容易出错。为此,ECMAScript 6 提供了全局符号注册表,可随时访问。
创建要共享的符号时,使用 `Symbol.for()` 方法而非 `Symbol()` 方法。`Symbol.for()` 方法接受一个字符串参数,作为要创建的符号的标识符,该参数也会用作符号的描述。示例如下:
```javascript
let uid = Symbol.for("uid");
let object = {};
object[uid] = "12345";
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"
```
`Symbol.for()` 方法会先在全局符号注册表中查找是否存在键为 `"uid"` 的符号。若存在,返回现有符号;若不存在,则创建新符号并使用指定键注册到全局符号注册表,然后返回新符号。后续使用相同键调用 `Symbol.for()` 会返回相同的符号,示例如下:
```javascript
let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"
let uid2 = Symbol.for("uid");
console.log(uid === uid2); // true
console.log(object[uid2]); // "12345"
console.log(uid2); // "Symbol(uid)"
```
还可通过 `Symbol.keyFor()` 方法检索全局符号注册表中与符号关联的键。示例如下:
```javascript
let uid = Symbol.for("uid");
console.log(Symbol.keyFor(uid)); // "uid"
let uid2 = Symbol.for("uid");
console.log(Symbol.keyFor(uid2)); // "uid"
let uid3 = Symbol("uid");
console.log(Symbol.keyFor(uid3)); // undefined
```
需要注意的是,全局符号注册表是共享环境,如同全局作用域,使用第三方组件时,可对符号键进行命名空间处理,以降低命名冲突的可能性。
#### 4. 符号强制类型转换
类型强制转换是 JavaScript 的重要部分,该语言在将一种数据类型转换为另一种数据类型方面有很大灵活性。但符号在强制类型转换方面缺乏灵活性,因为其他类型没有与符号逻辑等价的表示。具体而言,符号不能被强制转换为字符串或数字,以防止它们被意外用作本应表现为符号的属性。
可使用 `String()` 函数获取符号的字符串描述,示例如下:
```javascript
let uid = Symbol.for("uid"),
desc = String(uid);
console.log(desc); // "Symbol(uid)"
```
但尝试将符号直接与字符串连接会抛出错误,示例如下:
```javascript
var uid = Symbol.for("uid"),
desc = uid + ""; // error!
```
同样,不能将符号强制转换为数字,所有数学运算符应用于符号时都会导致错误,示例如下:
```javascript
var uid = Symbol.for("uid"),
sum = uid / 1; // error!
```
#### 5. 检索符号属性
`Object.keys()` 和 `Object.getOwnPropertyNames()` 方法可检索对象中的所有属性名,前者返回所有可枚举属性名,后者返回所有属性,无论是否可枚举。但这两个方法都不会返回符号属性,以保留它们在 ECMAScript 5 中的功能。在 ECMAScript 6 中,新增了 `Object.getOwnPropertySymbols()` 方法,用于从对象中检索属性符号。示例如下:
```javascript
let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};
let symbols = Object.getOwnPropertySymbols(object);
console.log(symbols.length); // 1
console.log(symbols[0]); // "Symbol(uid)"
console.log(object[symbols[0]]); // "12345"
```
#### 6. 用知名符号暴露内部操作
ECMAScript 6 有预定义的知名符号,代表 JavaScript 中以前被视为内部操作的常见行为。每个知名符号由 `Symbol` 对象上的属性表示,例如 `Symbol.match`。常见的知名符号如下表所示:
| 知名符号 | 描述 |
| ---- | ---- |
| `Symbol.hasInstance` | 用于 `instanceof` 确定对象的继承关系 |
| `Symbol.isConcatSpreadable` | 布尔值,指示 `Array.prototype.concat()` 在接收集合作为参数时是否应展平集合元素 |
| `Symbol.iterator` | 返回迭代器的方法 |
| `Symbol.match` | 用于 `String.prototype.match()` 比较字符串的方法 |
| `Symbol.replace` | 用于 `String.prototype.replace()` 替换子字符串的方法 |
| `Symbol.search` | 用
0
0
复制全文
相关推荐










