语法
Symbol是一种基本数据类型,任何两个Symbol都不相等,创建方式如下
注意点
- Symbol()方法可以传描述字符串,也可以不传,不影响使用,方便调试而已。
- Symbol作为构造函数,却不能new Symbol(),这个一定要注意!!
- Symbol可以调用toString方法
let a = Symbol('a'); // Symbol(a)
let b = Symbol('a'); // Symbol(a)
let c = Symbol(); // Symbol()
let d = new Symbol(); // Uncaught TypeError: Symbol is not a constructor
console.log(a === b); // false
console.log(a.toString()); // 'Symbol(a)'
console.log(c); // Symbol()
作为对象的key
Symbol可以用来做对象的key,可以有如下使用
let a = Symbol('a');
let obj = { [a]:1 };
console.log(obj[a]); // 1
// 由于symbol不重复的特性,这里如果没有这个symbol的引用,是没有办法访问到这个属性的
全局注册的Symbol
Symbol提供Symbol.for()方法全局注册,如果全局已存在则直接返回,不存在则创建
提供Symbol.keyFor去访问该全局注册的symbol的描述字符串
let a = Symbol.for('a');
let b = Symbol.for('a');
let c = Symbol('c');
console.log(a === b); // true
console.log(Symbol.keyFor(a)); // 'a'
console.log(Symbol.keyFor(c)); // undefined
let a = Symbol('a');
let obj = { [a]:1 };
console.log(obj[a]); // undefined
解决命名冲突
如果有两个文件同时要往一个公共的对象里写入数据那么会发生如下的情况
// a.js
import common from './common'
common.test = '123'
//b.js
import common from './common'
common.test = '234'
console.log(common.test);// '234'
那如果我们使用Symbol的话就可以避免
// a.js
import common from './common'
let test = Symbol('test');
common[test] = '123'
// b.js
import common from './common'
let test = Symbol('test');
common[test] = '234'
// 这样在两个地方,得先能拿到这个Symbol的引用才能取访问这个属性,进而修改这个属性
模拟私有属性
刚才像上面描述的,其实已经有表达私有属性的意思了。我们访问一个对象的某个属性,如果这个属性时个symbol,我们需要先去拿到这个symbol的引用才能顺利访问;
之所以说是模拟,是因为有其他的办法可以访问到的
let a = Symbol('a');
let obj[a] = 1;
let symKeys = Object.getOwnPropertySymbols(a); // [Symbol(a)]
console.log(symKeys[0]); //Symbol(a)
console.log(obj[symKeys[0]]); // 1
总结
Symbol数据类型有什么用?
- 解决命名冲突
- 模拟私有属性