-
概述
ES5的对象属性名字都是字符串,容易造成属性名的冲突。例如你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与现有的方法耦合冲突。
这时候ES6引入了一种新的机制(第七种数据类型)Symbol
,它能保证对象内每条属性的名字独一无二。
Symbol
值通过Symbol函数
生成,也就是说对象的属性名现在有两种类型:原有的String
类型以及新增的Symbol
类型。只要属性名输入Symbol
类型,就是独一无二的,可以保证避免生耦合冲突。
let s = Symbol();
typeof s // "symbol"
需要注意的是,Symbol函数
前不能使用new
命令,否则会报错。因为生成的Symbol
是一个原始类型的值,不是对象。也就是说,由于Symbol
值不是对象,所以不能给它添加属性。基本上它是一种类似于字符串的数据类型。
Symbol函数
接受一个字符串参数,表示对Symbol
实例的描述,方便调试时区分。
var s1 = Symbol('foo');
var s2 = Symbol('bar');
s1// Symbol(foo)
s2// Symbol(bar)
Symbol函数
的参数指标是对当前Symbol值
的描述,因此相同参数的Symbol函数
的返回值是不相等的。
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 //false;
var t1 = Symbol('foo');
var t2 = Symbol('foo');
t1 === t2 //false;
Symbol值
不能参与其他类型的计算,否则报错,也就是说Symbol值
参与其他类型的计算不存在隐式转换
var sym = Symbol('foo');
"your Symbol is " + sym
// TypeError: Cannot convert a Symbol value to a string
1+sym
// TypeError: ...
但是Symbol值
能显式转换为字符串和布尔值,但不能转为数字。
var sym = Symbol('foo');
String(sym) //"Symbol(foo)"
sym.toString() // "Symbol(foo)"
Boolean(sym) // true
Number(sym) //Cannot convert a Symbol value to a number
-
作为属性名的 Symbol
由于每个Symbol
值的唯一性(不相等),这代表Symbol值
可以作为标识符用于对象的属性名,保证不会重名的属性。
作为对象属性名的三种写法
var mySymbol = Symbol();
var a = {}
///第一种
a[mySymbol ] = "hello"
///第二种
var a = {
[mySymbol]: "hello"
}
///第三种
var a = {};
Object.defineProperty(a,mySymbol,{value:'hello'})
以上三种方法都能得到相同的结果。但就是不能使用点操作符。
-
Symbol.for(),Symbol.keyFor()。
有时候我们需要重新使用同一个Symbol值
,Symbol.for()
方法可以做到这一点。只需要传入相同字符。
var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 //true
Symbol()
和Symbol.for()
两种方法,都会产生Symbol值
,不同点是Symbol.for()
产生的值会登记在全局环境中供搜索,而Symbol()
则不会,Symbol.for()
在被调用时不会每次都产生新的值,而是优先判断给定的key是否已经存在。
Symbol.keyFor()
方法返回一个已经登记的Symbol()
类型值的key
var s1 = Symbol.for('foo');
Symbol.keyFor(s1) // 'foo'
var s2 = Symbol('foo');
Symbol.keyFor(s2) //undefined
上面
s2
并没有登记,所以返回undefined
总结
Symbol
类型是第七种数据类型,它具有唯一性。通过Symbol
函数得到的类型都不相等(产生的值不会在全局登记
)。Symbol
类型不存在隐式转换,也就是不能参与其他类型的计算。但是它可以显式的转换为字符串和布尔值。
网友评论