用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
基本用法
// 需要使用Symbol函数初始化,不可以使用new操作符,为了防止出现包装对象的情况
let sym = Symbol();
console.log(typeof sym); // symbol
// 如需使用对象形式的可以自行包装
let mySymbol = Symbol();
let myWrappedSymbol = Object(mySymbol);
console.log(typeof myWrappedSymbol); // "object"
// 可以传入参数,做作为符号描述,但是和标识本身并无关系
let fooSymbol = Symbol('foo');
let otherFooSymbol = Symbol('foo');
console.log(fooSymbol == otherFooSymbol); // false
你只要创建 Symbol()实例并将其 用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。
全局注册表
用Symbol.for(‘foo’),可以重用全局内已有符号,不传参数,会返回 Symbol(undefined)。
let fooGlobalSymbol = Symbol.for('foo'); // 创建新符号
let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
用 Symbol.keyFor() 搜索全局注册表,如果不是注册过得Symbol返回undefined ```javascript // 创建全局符号 let s = Symbol.for(‘foo’); console.log(Symbol.keyFor(s)); // foo // 创建普通符号 let s2 = Symbol(‘bar’); console.log(Symbol.keyFor(s2)); // undefined
/ 如果全局搜索不到,会报错 / Symbol.keyFor(123); // TypeError: 123 is not a symbol
<a name="cpDS6"></a>
### 作为对象的属性使用
- 设置set操作
```javascript
let s1 = Symbol('foo'),
s2 = Symbol('bar'),
s3 = Symbol('baz'),
s4 = Symbol('qux');
// 直接设置
let o = {
[s1]: 'foo val'
};
// 属性设置
Object.defineProperty(o, s2, {value: 'bar val'});
// 多属性设置
Object.defineProperties(o, {
[s3]: {value: 'baz val'},
[s4]: {value: 'qux val'}
});
- 取出get操作
```javascript
let s1 = Symbol(‘foo’),
let o = { [s1]: ‘foo val’, [s2]: ‘bar val’, baz: ‘baz val’, qux: ‘qux val’ }; // getOwnPropertySymbols 和 getOwnPropertyNames 二者取出来的内容互斥 // 1. getOwnPropertySymbols取出symbol的属性和key // 2. getOwnPropertyNames 取出不是常规的属性和key — 非symbol定义的s2 = Symbol('bar');
console.log(Object.getOwnPropertySymbols(o)); // [Symbol(foo), Symbol(bar)] console.log(Object.getOwnPropertyNames(o)); // [“baz”, “qux”]
// 3. getOwnPropertyDescriptors可以取出所有的属性和key console.log(Object.getOwnPropertyDescriptors(o)); // {baz: {…}, qux: {…}, Symbol(foo): {…}, Symbol(bar): {…}}
// 4. Reflect.ownKeys(), 取出所有的key console.log(Reflect.ownKeys(o)); // [“baz”, “qux”, Symbol(foo), Symbol(bar)]
- **注意: ** 如果 没有显式地保存对这些属性的引用,那么必须遍历对象的所有符号属性才能找到相应的属性键 。
```javascript
let o = {
[Symbol('foo')]: 'foo val',
[Symbol('bar')]: 'bar val'
};
console.log(o);
// {Symbol(foo): "foo val", Symbol(bar): "bar val"}
let barSymbol = Object.getOwnPropertySymbols(o)
.find((symbol) => symbol.toString().match(/bar/));
console.log(barSymbol);
// Symbol(bar)
常用内置符号
- Symbol.asyncIterator —- 异步迭代和 for-await-of 循环
- Symbol.hasInstance —- instanceof 操作符使用
- Symbol.isConcatSpreadable —- 是否可以使用 Array.prototype.concat() 方法,如果为false,不会打平数组
- Symbol.iterator —- for-of 语句使用
- Symbol.match —- String.prototype.match()方法使用,可以改变正则的默认返回形式
- Symbol.replace —- String.prototype.replace()方法使用 , 可以重写replace的实现
- Symbol.search —- String.prototype.search()方法使用, 获取正则开始索引
- Symbol.species —- 用于替换当前的instanceof的实例对象
- Symbol.split —- String.prototype.split()方法使用
- Symbol.toPrimitive —- 该方法将对象转换为相应的原始值,可以控制返回的原始行为。对象默认行为返回[object Object] 可以使用这个符号,转换为输出其他内容 p54
- Symbol.toStringTag —- Object.prototype.toString()使用,对象默认行为返回[object Object] 可以使用这个符号,转换为输出 [object 其他内容]
- Symbol.unscopables —- 可以排除在with使用环境外(不推荐使用)