看源码碰到symbol,一脸懵......

640 阅读2分钟

最近初看react源码时,看见了symbol一脸懵,虽然知道有这个东西,但是不知道是用来做什么的。 于是决定好好搞明白,就有了这篇文章。

1. symbol是什么

symbol是一种基本数据类型,于ES6引入,用于表示唯一且不可变的值

2. 创建symbol

有两种主要方式创建Symbol

  1. Symbol(description):

创建一个新的 Symbol,并可以提供一个可选的描述字符串

const v1=Symbol('111')
console.log(v1);//Symbol(111)
  1. Symbol.for(key):

在全局注册表中查找或创建一个 Symbol

如果全局注册表中已经存在与 key 对应的 Symbol,则返回该 Symbol;否则,创建一个新的 Symbol 并注册到全局注册表中。

const v1=Symbol.for('111')
console.log(v1);//Symbol(111)

3. Symbol的特性

唯一性

每次调用Symbol(),都会生成一个唯一的值,即使单位相同

const v1=Symbol('111')
const v2=Symbol('111')
console.log(v1===v2);//false

不可变性

Symbol一旦创建,就无法被修改

let v1=Symbol('111')
console.log(v1.description);//111
v1=Symbol('112')
console.log(v1.description);//112
v1.description='123'
console.log(v1);//Symbol(112)修改失败,无效

其中Symbol 的描述(description 属性)是只读的,不能被修改

为什么v1被成功改变了?因为v1是一个变量,他只是对symbol值的引用

不会被枚举

Symbol作为对象属性的键时,不会被 for...inObject.keys()JSON.stringify() 等方法枚举:

const obj={
    [Symbol('key')]:'value',
    ['one']:1,
    normalKey:'normalValue',
}
console.log(obj);
//{ one: 1, normalKey: 'normalValue', [Symbol(key)]: 'value' }
console.log(Object.keys(obj));
//[ 'one', 'normalKey' ]
console.log(JSON.stringify(obj));
//{"one":1,"normalKey":"normalValue"}

全局注册表

使用 Symbol.for(key) 创建的 Symbol 会被存储在全局注册表中,可以通过 Symbol.keyFor(symbol) 查找其对应的 key

const v1=Symbol.for('111')
console.log(Symbol.keyFor(v1));//111

4. Symbol的用途

防止属性名冲突

在大型项目或库中,多个模块可能会向同一个对象添加属性。使用SYmbol作为属性名可以避免命名冲突:

const v1 = {
    [Symbol('key')]: '111',
};

const v2 = {
    [Symbol('key')]: '222',
};

const a = Object.getOwnPropertySymbols(v1); //[ Symbol(key) ]
const b = Object.getOwnPropertySymbols(v2); //[ Symbol(key) ]
console.log(v1[a[0]]);//111
console.log(v2[b[0]]);//222

Object.getOwnPropertySymbols 是 JavaScript 中的一个方法,用于获取一个对象的所有 Symbol 类型的属性键,以数组形式返回。它是 Object 对象的一个静态方法,专门用来处理对象中使用 Symbol 作为属性键的情况。

定义常量

Symbol 可以用来定义一组唯一的常量,确保它们不会与其他值冲突:

const COLOR_RED = Symbol('red');
const COLOR_GREEN = Symbol('green');
const COLOR_BLUE = Symbol('blue');

function getColorName(color) {
  switch (color) {
    case COLOR_RED:
      return 'Red';
    case COLOR_GREEN:
      return 'Green';
    case COLOR_BLUE:
      return 'Blue';
    default:
      return 'Unknown';
  }
}

console.log(getColorName(COLOR_RED)); // 'Red'

目前了解到这么多了,后面可能还会加~