一、概述说明
Symbol是一个新类型,属于原始数据类型,它的出现是为保证属性名的独一无二,防止属性名冲突。它可以接受一个字符串作为参数,表示对Symbol实例的描述,易于区分
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
二、Symbol.prototype.description
直接返回Symbol的描述
const sym = Symbol('foo');
sym.description // "foo"
三、作为属性名的Symbol
作为属性名的Symbol对象不会出现同名属性
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
注意:Symbol 值作为对象属性名时,不能用点运算符,必须放在方括号([])之中
let s = Symbol();
let obj = {
[s]: function (arg) { ... }
};
obj[s](123);
四、属性名的遍历
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回,使用Object.getOwnPropertySymbols()
方法可以获取Symbol属性名
const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
objectSymbols
// [Symbol(a), Symbol(b)]
使用 Reflect.ownKeys()
方法可以返回所有类型的键名
五、Symbol.for(),Symbol.keyFor()
-
Symbol.for()
该方法接受一个参数,搜索参数对应的Symbol值,存在则返回并注册至全局,不存在则新建一个以该参数为名称的Symbol值,并注册至全局
Symbol.for("bar") === Symbol.for("bar")
// true
Symbol("bar") === Symbol("bar")
// false
-
Symbol.keyFor()
返回一个已登记的 Symbol 类型值的描述(key
)
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
六、内置的Symbol值
1.Symbol.hasInstance
当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。
const Even = {
[Symbol.hasInstance](obj) {
return Number(obj) % 2 === 0;
}
};
1 instanceof Even // false
2 instanceof Even // true
12345 instanceof Even // false
2.Symbol.isConcatSpreadable
该属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开
let arr2 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = false;
['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
3.Symbol.species
创建衍生对象时,会使用该属性,定义Symbol.species
属性要采用get取值器
class MyArray extends Array {
static get [Symbol.species]() { return Array; }
}
const a = new MyArray();
const b = a.map(x => x);
b instanceof MyArray // false
b instanceof Array // true
4.Symbol.match、Symbol.replace、Symbol.search、Symbol.split
- 对象的
Symbol.match
属性,指向一个函数,执行str.match
时会调用它 - 对象的
Symbol.replace
属性,指向一个函数,执行String.prototype.replace
时会调用它 - 对象的
Symbol.search
属性,指向一个函数,执行String.prototype.search
时会调用它 - 对象的
Symbol.split
属性,指向一个函数,执行String.prototype.split
时会调用它
String.prototype.match(regexp)
// 等同于
regexp[Symbol.match](this)
class MyMatcher {
[Symbol.match](string) {
return 'hello world'.indexOf(string);
}
}
'e'.match(new MyMatcher()) // 1
5.Symbol.iterator
该属性指向该对象的默认遍历器方法
const myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
6.Symbol.toPrimitive
对象被转为原始类型的值时,会调用这个方法,该方法接受一个字符串参数,返回该对象对应的原始类型值
let obj = {
[Symbol.toPrimitive](hint) {
switch (hint) {
case 'number':
return 123;
case 'string':
return 'str';
case 'default':
return 'default';
default:
throw new Error();
}
}
};
2 * obj // 246
3 + obj // '3default'
obj == 'default' // true
String(obj) // 'str'
7.Symbol.toStringTag
这个属性可以用来定制[object Object]
或[object Array]
中object
后面的那个字符串
class Collection {
get [Symbol.toStringTag]() {
return 'xxx';
}
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"
8.Symbol.unscopables
对象的Symbol.unscopables
属性,指向一个对象。该对象指定了使用with
关键字时,哪些属性会被with
环境排除