# 介绍
Symbol
- 作用:作为对象属性的标识符
- 内置:静态属性、静态方法
- 特点:不支持new创建、Symbol()返回的Symbol值是唯一的
- 入参:String/其他类型会被转成字符串
const s1 = Symbol(1);
const s2 = Symbol(1);
console.log(s1 == 1); // false
console.log(s1 === s2); // false
console.log(typeof s1); // symbol
1
2
3
4
5
6
2
3
4
5
6
# 概念
概念表
名字 | 作用 | 例 |
---|---|---|
全局注册表 | 全局的一个键值对表 | |
描述符 | Symbol()或Symbol.for()时的入参 | 'hdy.name' |
键 | 定义时的描述符 | hdy.name |
值 | Symbol.for()的返回值 | Symbol(hdy.skill) |
# 方法
# for
- 作用:在
全局注册表中
注册或读取Symbol - 调用:Symbol.for(str)
- 返回:注册好的Symbol
- tip:查找
全局注册表
有没有相关描述的Symbol,有则返回,无则在全局注册表中创建
const s1 = Symbol.for('全局标记1');
const s2 = Symbol.for('全局标记1');
console.log(s1); // Symbol(全局标记1)
console.log(s1 === s2); // true
1
2
3
4
2
3
4
- 最佳实践:再全局注册表中加上前缀,减少全局污染
const hdy = Symbol.for('hdy.name');
const js = Symbol.for('hdy.skill');
console.log(Symbol.for('hdy.name')); // Symbol(hdy.name)
1
2
3
2
3
# keyFor
- 作用:拿到全局注册表的Symbol的键
- 调用:Symbol.keyFor(syb)
- 入参:Symbol
const js = Symbol.for('hdy.skill');
console.log(Symbol.keyFor(js)); // hdy.skill
1
2
2
# 属性
# description
- 原型属性:Symbol.prototype.description
- 类型:String
- 值:构造时的入参,和Symbol.keyFor()返回值一样
const s = Symbol('hdy');
console.log(s.description === 'hdy'); // true
1
2
2
- 其他类型会被转换成String
const a = Symbol(true);
console.log(typeof a.description); // string
1
2
2
- 和Symbol.keyFor()返回值一样
const js = Symbol.for('hdy.skill');
console.log(js.description === Symbol.keyFor(js)); // true
1
2
2
# hasInstance
- 作用:重写instanceof判断方式
- 调用:obj instanceof CLASS
// 改写 instanceof 默认判断
class A {
static [Symbol.hasInstance]() {
return true;
}
}
const a = '';
const b = 1;
const c = false;
console.log(a instanceof A); // true
console.log(b instanceof A); // true
console.log(c instanceof A); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# isConcatSpreadable
- 作用:调用数组concat连接时是否展开
- 类型:Boolean
- 默认:true
# iterator
Symbol.iterator
- 作用:获取对象迭代器的函数
- 调用:for...of
- 返回:Iterator
特殊
configurable | value |
---|---|
configurable | false |
enumerable | false |
writable | false |
- 对象默认不可以被for...of 迭代
const obj = {
name: 'hdy',
age: 18,
}
// TypeError: obj is not iterable
// for (let value of obj) { }
// 增加迭代器
obj[Symbol.iterator] = function* () {
const keys = Object.keys(this);
for(let key of keys) {
yield obj[key];
}
}
for (let value of obj) {
console.log(value); // hdy 18
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# asyncIterator
- 作用:异步迭代器
- 调用:for await (...of...) {}
- 难点:每一层await都会包装一次Promise,影响执行顺序
# match
- 作用:以正则的规则去匹配调用者
- 调用:str.match(RegExp)
- 值:Function(String.prototype.match调用的方法)/Boolean (判断是否用正则匹配,false就转换字符串匹配)
特殊
configurable | value |
---|---|
configurable | false |
enumerable | false |
writable | false |
# matchAll
- 作用:同match
- 调用:String.prototype.matchAll()
# replace
- 作用:同match
- 调用:String.prototype.replace()
# search
- 作用:同match
- 调用:String.prototype.search()
# split
- 作用:同match
- 调用:String.prototype.split(reg)
const s = '1$2$3';
const reg = /\$/;
console.log(s.split(reg)); // [ '1', '2', '3' ]
// 修改默认做法
reg[Symbol.split] = (str) => ['嘿', '嘿嘿', '嘿嘿嘿'];
console.log(s.split(reg)); // [ '嘿', '嘿嘿', '嘿嘿嘿' ]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# species
- 作用:决定此对象衍生出来的对象的构造类
- 原生构造类
class MyArray extends Array {}
const a = new MyArray(1, 2, 3);
const mapped = a.map(x => x);
console.log(mapped instanceof MyArray); // true
console.log(mapped instanceof Array); // true
1
2
3
4
5
6
2
3
4
5
6
- 修改后:本类的实例 => 的衍生对象 => 的构造类,做出了修改
class MyArray extends Array {
static get[Symbol.species]() {
return Array; // 衍生对象的构造函数就是Array构造,和MyArray没有关系
}
}
const a = new MyArray(1, 2, 3);
const mapped = a.map(x => x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# toPrimitive
- 作用:默认转化类型时使用
- 调用:+str/
${obj.str}
/!str/等 - 入参hint:'number'|'string'| 'default'
const obj = {};
console.log(+str + 3); // NaN
obj[Symbol.toPrimitive] = (hint) => 1000;
console.log(+str + 3); // 1003
1
2
3
4
5
2
3
4
5
# toStringTag
- 作用:Object.prototype.toString()会拿到此方法返回值做拼接
class A {}
const a = new A();
console.log(a.toString()); // [Object object]
Object.defineProperty(A.prototype, Symbol.toStringTag, {
get() {
return 'A';
}
})
console.log(a.toString()); // [Object A]
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# unscopables
- 作用:使用with更换作用域时时排除的属性名称
- tip:《红宝书》不建议使用with,代码不易读不易维护