目录
Object.getOwnPropertySymbols()
Symbol
Symbol 值通过Symbol
函数生成,而每个Symbol函数生成的值都是不同的。可以用于对象的属性来确保不会与其他属性名产生冲突。
let s = Symbol();
typeof s
// "symbol"
Symbol()函数
Symbol
函数前不能使用new
命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。
Symbol
函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,可以转为字符串时,注意即使相同的描述(参数),函数产生的值也不同。
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 // Symbol(foo)
s2 // Symbol(foo)
s1==s2 // false
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(foo)"
注意:Symbol值不能和其它原始值进行运算。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
作为对象属性用法
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
注意上面Symbol 值作为对象属性名时,不能用点运算符(因为点运算符会将后面连接的变量转换为字符串)。
作为对象属性遍历方法
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。
Object.getOwnPropertySymbols()
可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 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 键名。
let obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
};
Reflect.ownKeys(obj)
// ["enum", "nonEnum", Symbol(my_key)]
Symbol实例的属性
Symbol.prototype.description
指向Symbol函数的参数。
const sym = Symbol('foo');
sym.description // "foo"
Symbol函数上静态方法
Symbol.for()
接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
当没有
以该参数作为名称的 Symbol 值时,Symbol.for()
与Symbol()
这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索(见下面Symbol.keyFor),后者不会。
Symbol.keyFor()
返回一个全局已登记的 Symbol 类型值的key
。下面s1是用Symbol.for函数注册的全局变量,所以返回'foo',而s2不是全局变量,故返回undefined。
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
对象中内置Symbol值属性
ES6 提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。一些语句就是调用对象中的内置的这些方法,例如下面第一个foo instanceof Foo
在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)
。
Symbol.hasInstance
对象的Symbol.hasInstance
属性,指向一个内部方法。当其他对象使用instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo
在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)
。
Class MyClass {
[Symbol.hasInstance](foo) {
return foo instanceof Array;
}
}
[1, 2, 3] instanceof new MyClass() // true
Symbol.toStringTag
用于修改obj.toString()和obj.toLocalString()返回的值
const obj = {
[Symbol.toStringTag]:'objString'
}
obj.toString()
// '[object objString]'
Symbol.isConcatSpreadable
Symbol.species
Symbol.match
Symbol.replace
Symbol.split
Symbol.iterator
Symbol.toPrimitive
Symbol.unscopables
以下见链接
symbol应用
类的私有属性
例如下面代码,通过Symbol实现了类的私有属性,只有Person类中的成员方法才能调用私有的属性和方法,在外部无法访问到。
const Person = (function () {
const Key_name = Symbol('name')
const Key_say = Symbol('say')
class Person {
constructor(name) {
this[Key_name] = name
}
[Key_say](){
console.log('KeySay')
}
sayHello(){
console.log(`hello ${this[Key_name]}`)
this[Key_say]()
}
}
return Person
})()
let a = new Person('pyf')
a.sayHello()
//hello pyf
// KeySay
a[Symbol('name')] //undefined
a[Symbol('say')] //undefined