JavaScript基本对象Symbol研究_01_基本介绍_Symbol构造函数_静态方法_Symbol.for()、Symbol.keyFor()

JavaScript基本对象Symbol研究_01_基本介绍_Symbol构造函数_静态方法_Symbol.for()、Symbol.keyFor()

在ES6(ECMAScript 2015)中,Symbol是一种新的原始数据类型,表示独一无二的值。它是继NumberStringBooleanNullUndefined之后的第七种数据类型。Symbol的引入为对象属性名提供了唯一的标识符,避免属性名的冲突,尤其在对象需要扩展时。

本文将深入探讨Symbol的基本概念、Symbol构造函数以及重要的静态方法Symbol.for()Symbol.keyFor(),帮助您全面理解Symbol在JavaScript中的应用。

一、基本介绍

1. 什么是Symbol?

Symbol是原始数据类型的一种,表示独一无二的值。每个从Symbol()函数返回的Symbol值都是唯一的,即使它们的描述(description)相同。

let sym1 = Symbol('foo');
let sym2 = Symbol('foo');

console.log(sym1 === sym2); // 输出: false

2. Symbol的用途

  • 作为对象的唯一属性键:使用Symbol作为对象的属性名,可以确保属性不被意外覆盖或访问。

  • 实现私有属性:通过Symbol,可以模拟对象的私有属性,防止外部直接访问。

  • 元编程Symbol内置了一些预定义的Symbol值(如Symbol.iterator),用于改变语言内部行为,实现迭代器等高级功能。

3. 创建Symbol

创建Symbol值需要调用Symbol()函数,不能使用new关键字,因为Symbol不是构造函数。

let sym = Symbol('description');
  • description(可选):一个字符串,表示对Symbol值的描述,主要用于调试和日志记录。

二、Symbol构造函数

1. 基础语法

let sym = Symbol([description]);
  • description:对Symbol的描述,便于调试。

2. 示例代码

let sym = Symbol('mySymbol');
console.log(sym);               // 输出: Symbol(mySymbol)
console.log(typeof sym);        // 输出: "symbol"

3. 注意事项

  • Symbol值是唯一的:即使描述相同,Symbol值也不相等。

  • Symbol不能与其他类型进行运算Symbol值不能参与算术运算或字符串拼接。

    let sym = Symbol('test');
    console.log(sym + ''); // 报错:Cannot convert a Symbol value to a string
    
  • 转换为字符串:可以使用String()函数或symbol.toString()方法。

    let sym = Symbol('test');
    console.log(String(sym));     // 输出: "Symbol(test)"
    console.log(sym.toString());  // 输出: "Symbol(test)"
    

三、Symbol的使用

1. 作为对象属性名

使用Symbol作为对象的属性名,可以避免属性名的冲突。

let symKey = Symbol('key');
let obj = {
  [symKey]: 'value'
};

console.log(obj[symKey]); // 输出: "value"

2. 定义不可枚举的属性

Symbol属性默认是不可枚举的,不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()返回。

let obj = {};
let sym = Symbol('hidden');

obj[sym] = 'secret';

for (let key in obj) {
  console.log(key); // 没有输出
}

console.log(Object.keys(obj));                   // 输出: []
console.log(Object.getOwnPropertyNames(obj));    // 输出: []

3. 获取Symbol属性

可以使用Object.getOwnPropertySymbols(obj)获取对象的所有Symbol属性。

let sym1 = Symbol('first');
let sym2 = Symbol('second');
let obj = {
  [sym1]: 'value1',
  [sym2]: 'value2'
};

let symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // 输出: [Symbol(first), Symbol(second)]

四、Symbol的静态方法

1. Symbol.for()

1.1 基础介绍

Symbol.for()方法用于在全局符号注册表中查找或创建一个Symbol。对于相同的键,Symbol.for()会返回相同的Symbol值。

1.2 语法
let sym = Symbol.for(key);
  • key:字符串,表示Symbol的键。
1.3 示例代码
let sym1 = Symbol.for('shared');
let sym2 = Symbol.for('shared');

console.log(sym1 === sym2); // 输出: true
1.4 使用场景
  • 跨文件或模块共享Symbol:使用Symbol.for()可以在不同的模块中共享相同的Symbol值。
1.5 注意事项
  • 全局注册表Symbol.for()使用的键在全局范围内有效,可能会导致命名冲突,需要注意键的唯一性。

2. Symbol.keyFor()

2.1 基础介绍

Symbol.keyFor()方法返回一个从全局注册表中找到的Symbol的键。

2.2 语法
let key = Symbol.keyFor(sym);
  • sym:一个通过Symbol.for()注册的Symbol
2.3 示例代码
let sym = Symbol.for('shared');
let key = Symbol.keyFor(sym);

console.log(key); // 输出: "shared"
2.4 使用场景
  • 获取全局Symbol的键:在需要根据Symbol值获取其全局键时,可以使用Symbol.keyFor()
2.5 注意事项
  • 仅适用于全局Symbol:对于非全局注册的SymbolSymbol.keyFor()返回undefined

    let localSym = Symbol('local');
    console.log(Symbol.keyFor(localSym)); // 输出: undefined
    

五、示例:Symbol.for()和Symbol()的区别

let localSym1 = Symbol('test');
let localSym2 = Symbol('test');

console.log(localSym1 === localSym2); // 输出: false

let globalSym1 = Symbol.for('test');
let globalSym2 = Symbol.for('test');

console.log(globalSym1 === globalSym2); // 输出: true

console.log(Symbol.keyFor(globalSym1)); // 输出: "test"
console.log(Symbol.keyFor(localSym1));  // 输出: undefined
  • Symbol()创建的Symbol是局部的,每次都会返回新的唯一值。

  • Symbol.for()会在全局注册表中查找,如果存在则返回已注册的Symbol,否则创建新的并注册。

六、Symbol的注意事项

  • 不能使用new关键字Symbol不是构造函数,直接调用即可。

    let sym = new Symbol(); // 报错:Symbol is not a constructor
    
  • Symbol不能被自动转换为字符串:在字符串拼接或其他需要字符串的地方,需要显式转换。

    let sym = Symbol('desc');
    console.log('Symbol is ' + sym); // 报错:Cannot convert a Symbol value to a string
    
    // 正确方式
    console.log('Symbol is ' + String(sym)); // 输出: Symbol is Symbol(desc)
    
  • Symbol作为对象属性时的访问:需要使用方括号[],不能使用点.

    let sym = Symbol('key');
    let obj = {
      [sym]: 'value'
    };
    
    console.log(obj[sym]); // 输出: "value"
    

小结

  • 使用Symbol可以创建唯一的值,避免属性名冲突。

  • Symbol()创建的Symbol是局部的,Symbol.for()创建的Symbol是全局注册的。

  • Symbol.keyFor()可以获取全局Symbol的键,对于局部Symbol返回undefined

  • Symbol在对象属性名中的使用需要注意访问方式,使用[]而不是.


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

It'sMyGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值