Symbol的定义方式
1、Symbol()的方式
使用Symbol定义的Symbol类型的变量,都不相等
let symbol1 = Symbol()
let symbol12 = Symbol()
console.log(symbol1 == symbol12)
打印结果未false。可见symbol1和symbol2不相同
let symbol3 = Symbol()
symbol3.name = 'Javascript'
console.log(symbol3)//Symbol()
console.log(symbol3.name)//undefined
解释:symbol类型的变量并不是对象,我们可以把Symbol类型的变量看做是特殊的字符串。
但是我们可以给Symbol变量添加描述信息,并且可以通过description获取描述信息
let symbol4 = Symbol('学习Javascript')
console.log(symbol4)//Symbol(学习Javascript)
console.log(symbol4.description)//学习Javascript
2、通过Symbol.for()定义Symbol变量
Symbol.for定义的是全局的,并且会被保存起来。在定义时会先判断,如果已经定义过了就直接使用,如果没有定义过则定义并保存。
let symbol5 = Symbol.for('121')
let symbol6 = Symbol.for('234')
console.log(symbol5 === symbol6)//false
let symbol7 = Symbol.for('121')
console.log(symbol5 === symbol7)//true
Symbol.for方式定义的Symbol类型数据,还可以通过Symbol.keyFor()方法获取描述信息
let symbol8 = Symbol.for('1111')
console.log(Symbol.keyFor(symbol8))//1111
console.log(symbol8.description)//1111
let symbol9 = Symbol('12311')
console.log(Symbol.keyFor(symbol9))//undefined
console.log(symbol9.description)//12311
Symbol的使用
const gride={
'lisi':{js:100,cs:89},
'lisi':{js:66,cs:88},
}
console.log(gride)
可以看到两个lisi只能打印出一个,下面一个将上面的那个覆盖了
如果定义两个变量来处理呢
const use1 = 'lisi'
const use2 = 'lisi'
const gride = {
use1: { js: 100, cs: 89 },
use2: { js: 66, cs: 88 },
}
console.log(gride)
可以看到user1和user2被当做字符串处理了,这里需要将use1和use2添加中括号
const use1 = 'lisi'
const use2 = 'lisi'
const gride = {
[use1]: { js: 100, cs: 89 },
[use2]: { js: 66, cs: 88 },
}
console.log(gride)
但是结果还是只有一个lisi。其实,我们就可以使用Symbol来防止覆盖。因为Symbol类型的变量都不相等。
const use1 = {
name: 'lisi',
key: Symbol()
}
const use2 = {
name: 'lisi',
key: Symbol()
}
const gride = {
[use1.key]: { js: 100, cs: 89 },
[use2.key]: { js: 66, cs: 88 },
}
console.log(gride)
// 注意这里使用gride[]来获取某条数据
console.log(gride[use1.key])
console.log(gride[use2.key])
示例2
class Cache {
static data = {}
static set(name, value) {
this.data[name] = value
}
static get(name) {
return this.data[name]
}
}
const user = {
name: 'apple',
des: '用户信息'
}
const cart = {
name: 'apple',
des: '购物车'
}
Cache.set('apple', user)
Cache.set('apple', cart)
console.log(Cache.get('apple'))
只打印了第二条数据。我们再来看看使用Symbol的情况。
class Cache {
static data = {}
static set(name, value) {
this.data[name] = value
}
static get(name) {
return this.data[name]
}
}
const user = {
name: 'apple',
des: '用户信息',
key: Symbol('会员资料')
}
const cart = {
name: 'apple',
des: '购物车',
key: Symbol('购物车')
}
Cache.set(user.key, user)
Cache.set(cart.key, cart)
console.log(Cache.get(user.key))
console.log(Cache.get(cart.key))
扩展属性和对象属性保护-Symbol的使用
对象属性
let symbol = Symbol('这是一个Symbol类型')
let hd = {
name: 'lisi',
[symbol]: '1222'
}
for (const key in hd) {
console.log(key)//name
}
for (const key of Object.keys(hd)) {
console.log(key)//name
}
Symbol像是私有属性,通过for-in或者for-of获取不到
获取Symbol类型属性的方法:Object.getOwnPropertySymbols()
let symbol = Symbol('这是一个Symbol类型')
let hd = {
name: 'lisi',
[symbol]: '1222'
}
for (const key of Object.getOwnPropertySymbols(hd)) {
console.log(key)//Symbol(这是一个Symbol类型)
}
获取全部属性的方法:Reflect.ownKeys()
let symbol = Symbol('这是一个Symbol类型')
let hd = {
name: 'lisi',
[symbol]: '1222'
}
for (const key of Reflect.ownKeys(hd)) {
console.log(key)
/*
name
Symbol(这是一个Symbol类型)D
*/
}
扩展属性
let site = Symbol('这是一个Symbol')
class Student {
constructor(name) {
this.name = name
this[site] = '一年级'
}
getName() {
return `${this[site]} ${this.name}`
}
}
let student = new Student('lisi')
console.log(student.getName())//一年级 lisi
console.log(student[site])//一年级
for (const key in student) {
console.log(key)//name
}
从上面的例子可以看到虽然for-in方法获取不到Symbol类型数据,但是在对象里面可以使用