18888628835/Blog

Symbol

18888628835 opened this issue · 1 comments

Symbol

Symbol 首先可以解决对象属性名重复的问题,由于对象的属性名是字符串,很容易出现重复,Symbol 会产生独一无二的类字符串的数据类型,所以不会产生冲突。

Symblol 需要如何创建呢?由于生成的是简单数据类型,不是一个对象,所以 ES6规定生成 Symbol 不能使用 new 关键字。我们可以这样生成

const s=Symbol()
console.log(typeof s)//"symbol"
const s=Symbol()
console.log(s)//Symbol()
const b=Symbol()
console.log(b)//Symbol()
s===b //false

如果直接打印,会发现返回的都是 Symbol(),所以我们可以传入一个参数来添加描述 description。

const s=Symbol('s')
const b=Symbol('b')
undefined
s
//Symbol(s)
b
//Symbol(b)

也可以传一个对象,当传入一个对象时,会自动在内部调用 toString 方法

const CustomToString={
  toString(){
    return 'abc'
  }
}
const a=Symbol(CustomToString)
console.log(a)//Symbol(abc)

由于传入的参数只是描述,所以即使描述是一样的,生成的 Symbol 值也是不相等的。

Symbol('abc')===Symbol('abc')
//false

description

当我们需要区分 Symbol 时,可以通过传入的参数作为其描述来区分 Symbol,那么如果想获取其描述呢?

我们有两种方法:

  • 第一种调用 toString 方法
let a=Symbol('a')
a.toString()
"Symbol(a)"
  • 第二种使用 description 属性
let b=Symbol('b')
b.description
"b"

Symbol注意点

Symbol 作为对象的属性名时保证不会出现同名属性,但是我们如果想要读取属性,不能直接用点来读取,而要使用中括号读取。

let a={}
let sym=Symbol()
a.sym='123'
a.sym //'123'
a[sym] //undefined

这是因为当使用点的形式来读取对象的属性时,点后面的是字符串,所以实际上这是相等的

a['sym']===a.sym

而 Symbol 属性被保存在 sym 这个变量名中,如果需要引用,只能这样写

a[sym]===a['sym'] //false
a[sym]='456'
a[sym] //'456'

Symbol 的使用场景

知道了 Symbol 的优点,那么究竟 Symbol 有什么用途?

当我们需要一个独一无二的东西且这个东西并不重要时可以使用,比如,当我从后端拿来数据,但是发现需要渲染到页面上的数据没有唯一的 key,这时候不一定需要 uuid,也可以自己给 key 生成一个 symbol 值。

还有一个用途是可以消除魔术字符串。

魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

比如,当我使用 Redux 时,我可能会这样写

//页面1
dispatch({type:'add',payload})
//页面2
dispatch({type:'add',payload})
...

可以看到上面的add 就是魔术字符串。有可能很多个组件都会写这样的字符串,仔细看其实这个字符串也不是很重要,我们只是需要这个逻辑。

那么我可以这样写

//config
export const hashMap={
  ADD:Symbol(),
  REMOVE:Symbol(),
}
//页面1
dispatch({type:hashMap.ADD,payload})
//页面2
dispatch({type:hashMap.REMOVE,payload})
...

作为属性名的注意要点

Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

let a=Symbol()
obj[a]='123'
obj.b='456'
for(let i in obj){
  console.log(i)
  }
// '456'

目前关于 Symbol,实际应用的不是很多,就先介绍到这里,如果还有兴趣了解 Symbol 的 API,可以参见
Symbol

Symbol 其实出现在 JavaScript 的很多地方。

可以看看掘金上这篇文章:https://juejin.cn/post/6844903511960846350#heading-15