Symbol
Symbol(符号) 是ES6
新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识,不会发生属性冲突的危险
语法
-
基础使用
基础使用const s1Symbol = Symbol();
const s2Symbol = Symbol();
const obj = {
[s1Symbol]:'s1',
[s2Symbol]:'s2'
}
console.log(obj); -
传入描述
- Symbol(str): 其中str为字符串类型,作为Symbol的描述,将来可以通过这个字符串来调试代码。但是这个字符串参数与Symbol定义或者Symbol标识无关。
Symbol(str) 传入字符串参数,对Symbol进行描述const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'s1',
[s2Symbol]:'s2'
}
console.log(obj); -
全局
Symbol
注册表如果需要运行时的不同部分需要共享和重用Symbol实例,那么可以用一个字符串作为键,在全局符号注册表中创建并重用Symbol
-
通过
Symbol.for()
创建Symbol全局注册表。Symbol.key()接收的是字符串const sSymbol = Symbol.for('s');
const s1Symbol = Symbol.for('s');
console.log(sSymbol === s1Symbol); // true -
通过
Symbol.keyFor()
查询Symbol全局注册表。Symbol.keyFor()接收的是Symbol
,返回该Symbol
对应的字符串键。如果查询的Symbol
不是全局的,那么返回undefined
。const sSymbol = Symbol.for('s');
const s1Symbol = Symbol.for('s');
console.log(sSymbol === s1Symbol); // true
console.log(Symbol.keyFor(sSymbol)); // s
console.log(Symbol.keyFor(s1Symbol)); // s
-
属性
Symbol.iterator
Symbol.iterator 一个返回一个对象默认迭代器的方法。被 for...of 使用。
Symbol.match
Symbol.match 一个用于对字符串进行匹配的方法,也用于确定一个对象是否可以作为正则表达式使用。被 String.prototype.match() 使用。
Symbol.replace
Symbol.replace 一个替换匹配字符串的子串的方法. 被 String.prototype.replace() 使用。
Symbol.search
Symbol.search 一个返回一个字符串中与正则表达式相匹配的索引的方法。被String.prototype.search() 使用。
Symbol.split
Symbol.split 一个在匹配正则表达式的索引处拆分一个字符串的方法.。被 String.prototype.split() 使用。
Symbol.hasInstance
Symbol.hasInstance 一个确定一个构造器对象识别的对象是否为它的实例的方法。被 instanceof 使用。
Symbol.isConcatSpreadable
Symbol.isConcatSpreadable 一个布尔值,表明一个对象是否应该flattened为它的数组元素。被 Array.prototype.concat() 使用。
Symbol.unscopables
Symbol.unscopables 拥有和继承属性名的一个对象的值被排除在与环境绑定的相关对象外。
Symbol.species
Symbol.species 一个用于创建派生对象的构造器函数。
Symbol.toPrimitive
Symbol.toPrimitive 一个将对象转化为基本数据类型的方法。
Symbol.toStringTag
Symbol.toStringTag 用于对象的默认描述的字符串值。被 Object.prototype.toString() 使用。
语法
场景
-
用于精确的判断对象类型: 通过
Object.prototype.toString()
可以精准的判断数据类型,但是如果两个都为对象,那么可以通过Symbol.toStringTag
精准的判断是哪个对象类型const obj1 = { name: 'obj1' };
const obj2 = { name: 'obj2' };
console.log(Object.prototype.toString.call(obj1)); // [object Object]
console.log(Object.prototype.toString.call(obj2)); // [object Object]
const obj1s = { name: 'obj1s' };
Object.defineProperty(obj1s, Symbol.toStringTag, {
value: 'obj1s',
});
const obj2s = { name: 'obj2s' };
Object.defineProperty(obj2s, Symbol.toStringTag, {
value: 'obj2s',
});
console.log(Object.prototype.toString.call(obj1s)); // [object obj1s]
console.log(Object.prototype.toString.call(obj2s)); // [object obj2s]
Symbol.prototype.toSource
Symbol.prototype.toSource 返回该 Symbol 对象的源代码。该方法重写了 Object.prototype.toSource 方法
Symbol.prototype.toString
toString()
方法返回当前 symbol 对象的字符串表示。
Symbol
对象拥有自己的 toString
方法,因而遮蔽了原型链上的 Object.prototype.toString()
。
语法
symbol.toString();
Symbol.prototype.valueOf
Symbol.prototype.valueOf 返回该 Symbol 对象。该方法重写了 Symbol.prototype.valueOf 方法
Symbol.prototype[@@toPrimitive]
Symbol.prototype[@@toPrimitive] 返回该 Symbol 对象。
方法
Symbol.for(key)
Symbol.for(key) 使用给定的key搜索现有的symbol,如果找到则返回该symbol。否则将使用给定的key在全局symbol注册表中创建一个新的symbol。
Symbol.keyFor(sym)
Symbol.keyFor(sym) 从全局symbol注册表中,为给定的symbol检索一个共享的?symbol key。
symbol.valueOf()
语法
const symbol = Symbol("symbol");
console.log(symbol.valueOf()); // Symbol(symbol)
console.log(symbol.valueOf() === symbol); // true
symbol.toString()
语法
const symbol = Symbol("symbol");
console.log(symbol.toString()); // Symbol(symbol)
console.log(typeof symbol.toString()); // string
console.log(symbol.toString() === symbol); // false
操作
对象包装
-
通过**Object()**创建包装对象
const sSymbol = Symbol('s');
const wrappedSSymbol = Object(sSymbol);
console.log(wrappedSSymbol); // Symbol {Symbol(s), description: 's'} -
通过**new Symbol()**来创建包装对象
- 注意: Symbol() 函数不可以用作构造函数,不可以与new关键字一起使用。这样做是为了避免创建Symbol()包装对象
const sSymbol = new Symbol('s');
console.log(sSymbol); // Symbol is not a constructor
访问遍历
-
通过
object[symbol]
访问Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
console.log(obj[s1Symbol]); // aaa
console.log(obj[s2Symbol]); // bbb -
通过
object.symbol
访问Symbol
属性,结果为undefined
const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
console.log(obj.s1Symbol); // undefined
console.log(obj.s2Symbol); // undefined -
通过
for……in
遍历对象,不可遍历Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
for(let key in obj){
console.log(obj[key]);
} -
通过
Object.keys()
遍历对象,不可遍历Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
const result = Object.keys(obj);
console.log(result); // [] -
通过
Object.getOwnPropertyNames()
,不可获取Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); // [] -
通过
Object.hasOwnProperty()
,可以检测Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
const result = obj.hasOwnProperty(s1Symbol);
console.log(result); // true -
通过
Object.getOwnPropertySymbols()
,用于遍历Symbol
属性const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj = {
[s1Symbol]:'aaa',
[s2Symbol]:'bbb'
}
const result = Object.getOwnPropertySymbols(obj);
console.log(result); // [Symbol(s1), Symbol(s2)]