Symbol的学习参考了以下大大们的博客~仅为自己的学习笔记。
http://es6.ruanyifeng.com/#docs/symbol
1. Symbol的需求
在ES5中,对象的属性都是字符串,很容易引起命名冲突的问题。如果你写一个对象,需要有一些属性名你不想别人误操作或修改,则可以借助Symbol来完成。
2. Symbol的基本语法
Symbol为ES6引入的第七种数据类型,也是原始数据类型。表示独一无二的值。
2.1 Symbol()
一个Symbol类型的数据可以用Symbol函数创建,但注意由于不是对象,不能使用new!
let s1 = Symbol()
console.log(typeof(s1)) //symbol
Symbol函数可以接收一个字符串作为参数,传入的字符串是对Symbol的描述。方便我们区分。
let s2 = Symbol("s")
由于传入的字符串仅为描述,所以即使传入相同的描述,Symbol创建出来的数据仍然是独一无二的。
let s3 = Symbol("s")
console.log(s2 == s3) //false
console.log(s2 === s3) //false
Symbol函数还可以接收一个对象作为参数,但是会先调用对象的toString()方法,并将其返回值作为对Symbol的描述。
let obj = {
toString:function(){
return 'cjx'
}
}
let s4 = Symbol(obj)
console.log(s4) //Symbol(cjx)
2.2 Symbol.prototype.description
有时如果你想要查看一个symbol数据的描述,可以使用description方法,具体如下
let obj = {toString:function(){return 'cjx'}}
let s4 = Symbol(obj)
console.log(s4.description) //cjx
2.3 Symbol作为属性
由于Symbol这独一无二的特性,所以Symbol值我们一般用做对象的属性值。具体的写法如下:
let name = Symbol("name")
let age = Symbol("age")
let gender = Symbol("gender")
let obj = {
school:"bupt",
//第一种写法
[name]:"cjx"
}
//第二种写法
obj[age] = 18
//第三种写法
Object.defineProperty(obj, gender, { value: 'female' })
console.log(obj)
注意:使用Symbol的值做属性的时候,不能使用.属性名来访问,应使用[]来访问。如上例中,如果这样写会取不到
console.log("不应用.访问",obj.name)
console.log("应使用[]访问",obj[name])
2.4 Symbol属性的获取方式
使用Symbol 值作为属性名时,该属性是公有属性不是私有属性。
但要注意,使用for…in, for…of无法遍历到以Symbol值作为属性名的属性。
console.log("----for in----")
for(let key in obj){
console.log(key,obj[key])
}
console.log("----getOwnPropertySymbols----")
let SymbolAttr = Object.getOwnPropertySymbols(obj) //返回一个数组
for(let key of SymbolAttr)
{
console.log(key,obj[key])
}
console.log("----Reflect.ownKeys----")
let allAttr = Reflect.ownKeys(obj)
for(let key of allAttr)
{
console.log(key,obj[key])
}
从上面我们可以看到,使用for…in方法只能遍历到非Symbol值的属性。使用getOwnPropertySymbols只能获取到Symbol值的属性。使用Reflect.ownKeys可以获取到所有共有属性。
Symbol 作为属性名,该属性不会出现在for…in、for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
2.5 Symbol.for(), Symbol.keyFor()
2.5.1 Symbol.for()
Symbol.for()接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建这样一个Symbol值。
let s1 = Symbol.for('s')
let s2 = Symbol.for('s')
console.log(s1===s2) //true
这里还引入了一个登记机制的概念。使用Symbol.for创建的会被登记在全局环境中供搜索,而使用Symbol创建的不会被登记。
2.5.2 Symbol.keyFor()
Symbol.keyFor()方法会返回一个已登记的Symbol类型值的key,如:
let s1 = Symbol("s")
let s2 = Symbol.for("s")
console.log("未登记",Symbol.keyFor(s1))
console.log("登记",Symbol.keyFor(s2))