ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
符号(symbol)是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用。生成 Symbol 值的最简单的方式就是直接通过 Symbol 函数生成。
let sym = Symbol(); console.log(sym); // Symbol()
注意事项:
1.Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。
2.Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
let sym1 = Symbol("test"); let sym2 = Symbol("test"); console.log(sym1); // Symbol(test) console.log(sym2); // Symbol(test) console.log(sym1 == sym2); // false console.log(sym1 === sym2); // false
3.Symbol值不能与其他类型的值进行运算,会报错;
let sym = Symbol("test"); let str = "hello"; console.log(str + sym); // Uncaught TypeError: Cannot convert a Symbol value to a string(…)
symbol不能被隐式自动转换为字符串,这和语言中的其它类型不同,但是它可以显式转换为字符串。
var sym = Symbol(‘My symbol‘); String(sym) // ‘Symbol(My symbol)‘ sym.toString() // ‘Symbol(My symbol)‘
Symbol 值作为对象属性名
对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。
凡是属性名属于Symbol类型,就都是独一无二的,这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
var mySymbol = Symbol(); // 第一种写法 var a = {}; a[mySymbol] = ‘Hello!‘; // 第二种写法 var a = { [mySymbol]: ‘Hello!‘ }; // 第三种写法 var a = {}; Object.defineProperty(a, mySymbol, { value: ‘Hello!‘ }); // 以上写法都得到同样结果 a[mySymbol] // "Hello!"
注意,Symbol值作为对象属性名时,不能用点运算符获取属性值,只能用方括号
var symbol1 = Symbol(‘111‘); var symbol2 = Symbol(‘222‘); var obj = { // 定义 Symbol 属性时注意加上方括号 [symbol1]: ‘I am symbol1~‘ }; // 下面的语句相当于为 obj 添加了一个新属性 // 而这个属性名是一个字符串,不是上面定义的 Symbol obj.symbol2 = ‘I am symbol2~‘; console.log(obj); // { // symbol2: "I am symbol2~", // Symbol(111): "I am symbol1~", // __proto__: Object // } obj.symbol1 // undefined obj[symbol1] // "I am symbol1~" obj.symbol2 // "I am symbol2~" obj[symbol2] // undefined obj[‘symbol2‘] // "I am symbol2~"
Symbol.for(key)方法会根据给定的键 key,来从 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入 symbol 注册表中。
与此对应,还有一个方法:Symbol.keyFor(sym) 方法用来获取 symbol 注册表中与某个 symbol 关联的键。
let s1 = Symbol.for(‘s1‘); console.log(s1); // Symbol(s1) let s2 = Symbol.for(‘s1‘); console.log(s2); // Symbol(s1) console.log(s1 === s2); // true console.log(Symbol.keyFor(s1)); // s1 console.log(Symbol.keyFor(s2)); // s1 var sym1 = Symbol(); var sym2 = Symbol(); console.log(sym1 == sym2) //false
Symbol.for()
与Symbol()
这两种写法,都会生成新的Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()
不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key
是否已经存在,如果不存在才会新建一个值。