JavaScript - Symbol使用

在ES5中,对象的属性名都是字符串,这容易造成属性名的冲突(比如,在模块化应用中,如果你使用了一个其他人提供的对象,同时你又想为这个对象添加新的属性,这个新的属性的名字,就有可能和原来的对象中的属性名发生冲突,导致覆盖产生(结果把原模块的对象中的’a’属性的值覆盖了),如下例:

let obj = {a: 'a'}  // 引用其他模块的对象
obj['a'] = 'b' // 想添加一个'a'属性
console.log(obj); // {a: 'b'}

如果存在一种机制,保证每个属性的名字都是独一无二的,这样就能够防止属性的冲突了。于是在 ES6 引入 Symbol

1、Symbol()
SymbolUndefined、Null、Boolean、String、Symbol、Number类型一样,都属于原始数据类型。Symbol通过Symbol函数生成(注意:Symbol为原始数据类型,不能使用new命令)

let s1 = Symbol()
let s2 = Symbol()
console.log(typeof s1);  //symbol
console.log(s1 === s2);   //false

2、Symbol()的参数
Symbol函数也可以接收一个字符串作为参数,表示对Symbol实例的描述,这样做的目的是利于区分:
注意:Symbol()的参数只是表示对于当前Symbol值得描述,因此相同参数的Symbol的返回值是不相等的

//s1和s2都是Symbol值,如果不加参数,它们的输出都是Symbol,不利于区分
let s1 = Symbol()
let s2 = Symbol()

console.log(s1)//Symbol
console.log(s2)//Symbol

//参数只是一种描述,相同参数时,两个Symbol()的返回值并不相等
let s3 = Symbol('foo')
let S4 = Symbol('foo')

console.log(s3)//Symbol(foo)
console.log(s4)//Symbol(foo)
console.log(s3 === s4)//false

3、Symbol作为对象中的属性名

ES6引入Symbol后,对象中的属性名现在可以有两种,一种是本来就有的字符串,另一种则是新增的Symbol类型。由于每个Symbol值都是不同的,这就意味着,当一个对象由模块构成时,就能够发防止莫一个键被不小心改写或覆盖

let obj = {a: 'a'}
let a = Symbol()
obj[a] = 'b'
console.log(obj); // {a: 'a', Symbol(): 'b'}

注意Symbol值作为对象属性时,不能使用点运算符,因为点运算符后面接的是字符串。只能使用中括号,因为中括号内接表达式

let obj = {a: 'a'}
let a = Symbol()
obj[a] = 'b'
console.log(obj.a) // a
console.log(obj[a]) // b

4、属性名的遍历
Symbol 作为属性名,该属性不会出现在 for…infor…of 循环中,也不会被 Object.keys()Object.getOwnPropertyNames()JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有Symbol 属性名(以数组形式排列)


let obj = {a: 'js'}
let a = Symbol()
obj[a] = 'es'
for (const key in obj) {
    console.log(key); // a
}
for (const key of Object.getOwnPropertyNames(obj)) {
    console.log(key); // a
}
for (const key of Object.keys(obj)) {
    console.log(key); // a
}
console.log(JSON.stringify(obj)) // {"a":"js"}

5、Symbol.for()
我们希望重新使用同一个 Symbol 值, Symbol.for 方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol

let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1===s2) // true

6、Symbol()和Symbol.for()的区别、以及Symbol.keyfor()

  1. Symbol()每次被调用都会生成一个新的Symbol(一位内Symbol(写法没有登记机制,所以每次调用都会返回一个不同的值)
  2. Symbol.for()不会每次调用就返回一个新的Symbol,而是会先检查给定的key是否已经存在,如果不存在,则会在全局创建并注册这个key,然后才会新建一个Symbol
  3. Symbol.keyFor()方法返回一个已经登记的Symbol类型值的key
let s1 = Symbol.for("foo");
console.log(Symbol.keyFor(s1)); // "foo"
let s2 = Symbol("foo");
console.log(Symbol.keyFor(s2)); // undefined

7、内置的Symbol值

在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值