本文目录:
- 1.什么是Symbol
- 2.Symbol的应用场景
- 3.注意事项
- 4.Symbol.for方法
1.什么是Symbol
Symbol是es6中一种新增加的数据类型,它表示独一无二的值。es5中我们把数据类型分为基本数据类型(字符串、数字、布尔、undefined、null)和引用数据类型(Object),在es6中新增的Symbol数据类型划分到基本数据类型
为什么会有这样一种数据类型呢?
如下所示,当别人给了你一个定义好的对象:
var obj = {
name: "xiaoqiang",
showName: function(){alert(1)}
}
你拿到对象想给这对象添加新的属性和方法的时候,可能会创建出一个name属性和showName方法
obj.name = "nodeing"
obj.showName = function(){alert(2)}
这个时候,新增加的方法和属性就会去把原有的方法覆盖,这样就产生了冲突
由于对象的属性和方法是字符串组成,这样新增方法和属性的时候有可能冲突,在es6中就新增了一种数据类型,表示独一无二的值
通过Symbol函数可以创建一个独一无二的值
let s1 = Symbol()
let s2 = Symbol()
console.log(s1 === s2) //false 说明创建出来的s1和s2 并不是相同的
console.log(s1, s2); //Symbol() Symbol()
上述代码中,打印出来的值都是Symbol() , 怎样才能区分谁是s1,谁是s2呢?我们可以通过传参的形式来解决
let s1 = Symbol("s1")
let s2 = Symbol("s2")
console.log(s1, s2); //Symbol(s1) Symbol(s2)
传入的参数就是对当前Symbol的描述,用来区分Symbol
let name = Symbol()
let html = Symbol()
let obj2 = {
[name]:'xiaoli',
[html]:function(){
alert(3)
}
}
obj2[Symbol()] = 'hello'
console.log(obj2)
//Symbol():'xiaoli'
//Symbol():f()
//Symbol():'hello'
因为name和html在代码的最开始已经被我们定义成了变量,所以定义对象obj2的的时候,其中的key变量name和html我们的[]包裹了起来。
当最终输出obj2的时候,输出了三个不同的属性,这表示三个Symlbol并没有互相覆盖。
2.Symbol的应用场景
Symbol通常用于设置对象的属性名或者方法,防止新加入的属性或者方法与原来属性或者方法冲突
let name = Symbol("name");
let name = Symbol("name");
let show = Symbol("show");
let obj = {
//设置属性
[name]: 'xiaoqiang',
[show](){alert(1)}
};
//取值
console.log(obj[name]);
//调用方法
obj[show]()
上面的代码会报错Uncaught SyntaxError: Identifier 'name' has already been declared
3.注意事项
注意1: Symbol里面的参数仅仅是对Symbol的描述,没有其他意义,因此,即使描述相同,Symbol也是不同的
console.log(Symbol("hello") === Symbol("hello")) //false
注意2:Symbol函数不能使用New关键字调用
let s1 = new Symbol(); //报错
注意3: Symbol类型在做类型转换的时候不能转成数字
let s1 = Symbol("s1");
console.log(String(s1)); //Symbol(s1)
console.log(Boolean(s1)); //true
console.log(Number(s1)) //报错
注意4: Symbol不能做任何运算
console.log(Symbol("s1") + "world") //报错
console.log(Symbol("s1") - 100) //报错
注意5: Symbol在作为对象属性或者方法的时候,如果不赋值给一个变量的话,没有办法取值
let obj = {
//设置属性
[Symbol("name")]: 'xiaoqiang'
};
//取值
console.log(obj[Symbol("name")]);
输出结果为undefined,原因是上面的[Symbol("name")]和下面的 [Symbol("name")]不是同一个Symbol
注意6: Symbol没有办法被for in循环遍历
let name = Symbol('name')
let age = Symbol('age')
let obj = {
a: 1,
b: 2,
[name]: 'xiaoqiang',
[age]: 18
};
for(let attr in obj){
console.log(attr,obj[attr]) //a b
}
这时候可以使用Object.getOwnPropertySymbols查看对象上所有的symbol属性
console.log(Object.getOwnPropertySymbols(obj))
输出结果为一个Symbol组成的数组[Symbol(name), Symbol(age)]
4.Symbol.for方法
上面的主意点1讲了定义Symbol的时候,尽管描述相同,但是所生成的Symbol也是不同的,但是和 Symbol() 不同的是,用 Symbol.for() 方法创建的的 symbol 会被放入一个全局 symbol 注册表中。Symbol.for() 并不是每次都会创建一个新的 symbol,它会首先检查给定的 key 是否已经在注册表中了。假如是,则会直接返回上次存储的那个。否则,它会再新建一个。
比如下面这种情况
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1 === s2)
输出结果为true
也可以通过Symbol.keyFor把标识找出来
console.log(Symbol.keyFor(s1)) //foo
网友评论