前言
嘟三~ 嘟三~ 今日份广播题目:“怎么让JavaScript越来越6”。接下来,小菜鸡本人将和大家一起来探讨ES6-ES13的那些酷酷的新特性,从这次广播开始,你也可以炫耀:“这个ES新特性我都用得溜溜的!”
引子
ES6版本邀请了新的舞伴加入:Symbol、Set和Map,这三位舞伴各具特色,各自承担着不同的角色,使得JavaScript这个舞变得更加精彩。
一、Symbol
1.1. Symbol的基本使用
Symbol是什么呢?Symbol是ES6中新增的一个基本数据类型,翻译为符号。
那么为什么需要Symbol呢?
- 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突
- 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖掉它内部的某个属性
- 比如我们前面在讲apply、call、bind实现时,我们有给其中添加一个fn属性,那么如果它内部原来已经有了fn属性了呢?
- 比如开发中我们使用混入【Mixin】,那么混入中出现了同名的属性,必然有一个会被覆盖掉
Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
- Symbol值是通过Symbol函数来生成的,生成后可以作为属性名
- 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol
const s = Symbol()
console.log(s) // Symbol()
你无论怎么召唤他,他每次都会以一个全新的面孔出现
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2) // false
我们也可以在创建Symbol值的时候传入一个描述description【这个是ES2019(ES10)新增的特性】
const s3 = Symbol("abc")
console.log(s3.description)
1.2. Symbol作为属性名
Symbol的独特性使得他成为了一个好帮手。当你需要一个完全不会冲突的属性名时,你可以找到Symbol
写法一: 属性名赋值
const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {
}
obj[s1] = "abc"
obj[s2] = "cba"
写法二: Object.defineProperty
const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {
}
Object.defineProperty(obj, s1, {
enumerable: true,
configurable: true,
writable: true,
value: "abc"
})
写法三: 定义字面量是直接使用
const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {
}
const info = {
[s1]: "abc",
[s2]: "cba"
}
之后我们可以通过Symbol值来获取值:
console.log(info[s1]) // abc
console.log(info[s2]) // cba
// 不能这样获取
console.log(info.s1) // undefined
但是通过Symbol添加的属性名,在遍历时,是无法获取到的:
console.log(Object.keys(info))
console.log(Object.getOwnPropertyNames(info))
如果我们希望获取Symbol的key,那么需要通过 Object.getOwnPropertyNames:
console.log(Object.getOwnPropertySymbols(info))
const symbolKeys = Object.getOwnPropertySymbols(info)
for (const key of symbolKeys) {
console.log(info[key])
}
1.3. 相同值的Symbol
Symbol精灵的独特并不意味着他不能分享他的秘密。当你使用Symbol.for()召唤他的时候,他会首先翻阅他的记事本,看看你是不是之前就已经拜访过他,如果是的话,他就会带着他上次的面孔再次出现。
- 我们可以使用Symbol.for方法来做到这一点
- 并且我们可以通过Symbol.keyFor方法来获取对应的key
const s1 = Symbol.for("abc")
const s2 = Symbol.for("abc")
console.log(s1 === s2) // true
const key = Symbol.keyFor(s1)
console.log(key) // abc
const s3 = Symbol.for(key)
console.log