Symbol: ES6 引入的一种新的原始数据类型,表示独一无二的值。(undefined,null,布尔值,数值,字符串,Symbol,对象,大整形)
Symbol 的引入能很好的避免给对象添加属性时,属性名的冲突;需要注意的是,当Symbol作为属性名的时候要用中括号包裹而不能使用点运算符,点运算符后面是字符串而不是变量。
Symbol 能够转换成字符串和布尔值,但是不能转换成数值类型,同时Symbol数据不能参与运算,否则会报错
let s = Symbol(); // 不能使用new命令,否则会报错 typeof s // "symbol" // 能够接受参数 let s1 = Symbol('foo'); let s2 = Symbol('bar'); s1 // Symbol(foo) s2 // Symbol(bar) s1.toString() // "Symbol(foo)" s2.toString() // "Symbol(bar)" // 没有参数的情况 let s1 = Symbol(); let s2 = Symbol(); s1 === s2 // false // 有参数的情况 let s1 = Symbol('foo'); let s2 = Symbol('foo'); s1 === s2 // false
2、Symbol.prototype.description()
let sym = Symbol("foo") // sym 的描述就是字符串 foo ;当我们要读取这个描述的时候,就要将sym转换成字符串,ES2019 添加了一个实例属性description,直接返回 Symbol 的描述。
const sym = Symbol('foo'); String(sym) // "Symbol(foo)" sym.toString() // "Symbol(foo)" sym.description // "foo"
3、Symbol 消除魔术字符串
魔术字符串是指: 代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。当需要修改这个字符串时,就需要修改多处,因此应该用变量来代替;
4、Symbol 作为属性名被遍历时,并不会被遍历到(for...in, for...of, Object.keys(), JSON.stringify(), getOwnPropertyNames());但是可以通过Object.getOwnPropertySymbols() 获取到,该方法获得的是以Symbol作为属性名的Symbol值组成的一个数组;
另外新的API Reflect.keys() 能够获取到对象所有的键名组成的数组;
5、Symbol.for() 接受一个参数,先搜索有无以该参数为名称的Symbol值,如果有就返回这个Symbol值,如果没有就生成一个以该参数为名称的Symbol值
1 let s1 = Symbol.for('foo'); 2 let s2 = Symbol.for('foo'); 3 4 s1 === s2 // true 5 6 // 实际上 s1 和 s2 是同一个值; 7 8 // Symbol() 和 Symbol.for() 生成的值得区别为,Symbol() 每次调用都会生成新的Symbol类型的值,而 Symbol.for() 会先搜索是否有该参数值得,多处调用时,如果搜索到就不会生成新的Symbol类型的值; 9 // 同时 Symbol.for() 生成的是全局的值,登记在全局
Symbol.keyfor() 是返回Symbol类型值登记时的名称,没有登记的返回undefined;
let s1 = Symbol.for("foo"); // 登记在全局 Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); // 未登记 Symbol.keyFor(s2) // undefined
6、 内置的Symbol值
由于Symbol独特的性质,ES6提供了内置的Symbol值指向语言内部使用的方法。
1、Symbol.hasInstance 当对象使用 instanceof 运算符时,就会自动调用这个方法;
class MyClass { [Symbol.hasInstance](foo) { return foo instanceof Array; } } [1, 2, 3] instanceof new MyClass() // true
2、Symbol.isConcatSpreadable 值是一个布尔值,表示 Array.prototype.concat() 调用时,传入的数组是否是可以展开的;数组默认是true展开,类数组则相反;
3、Symbol.species 指向一个构造函数;当创建衍生对象时,就会使用对象的该属性;
4、对象的Symbol.match属性,指向一个函数。当执行 String.prototype.match() 时,如果该属性存在就会调用它,返回方法的返回值。
5、Symbol.replace, 同上, 只是执行 String.prototype.replace() 时
6、Symbol.split, 同上,是执行 String.prototype.split() 时
7、Symbol.search, 同上,是执行 String.prototype.search() 时
8、Symbol.iterator, 指向该对象默认遍历器的方法,当对象进行 for ... of 进行遍历时,就会执行该方法。
9、Symbol.toPrimitive, 指向方法,当该对象转换成一个原始类型的值(数值,字符串,数值 || 字符串)时就会调用这个方法;
10、Symbol.toStringTag, 对象的Symbol.toStringTag
属性,指向一个方法。在该对象上面调用Object.prototype.toString
方法时,如果这个属性存在,它的返回值会出现在toString
方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object]
或[object Array]
中object
后面的那个字符串。
11、Symbol.unscopables 对象的Symbol.unscopables
属性,指向一个对象。该对象指定了使用with
关键字时,哪些属性会被with
环境排除。