概述
Symbol是一种基本数据类型(primitive data type)
- 它的功能类似于一种标识唯一性的ID。
- 每个从Symbol()返回的symbol值都是唯一的。
- 一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的。
语法
Symbol([description])
使用方法
通过调用Symbol()
函数可以创建一个Symbol实例。同时可以传入一个字符串作为描述信息。
//无描述
let symbol1 = Symbol();
//有描述
let symbol2 = Symbol("I'm a description");
相关属性
检查类型,返回symbol
const symbol1 = Symbol();
console.log(typeof symbol1); //"symbol"
每个Symbol实例都是唯一的
console.log(Symbol('foo') === Symbol('foo')); //false
长度
Symbol.length //0
原型
Symbol.prototype
使用场景
场景1:使用Symbol来作为对象属性名(key)
我们通常定义或访问对象的属性时使用字符串
let obj = {
"keyName": "keyValue"
}
obj["keyName"] // 'keyValue'
Symbol可同样用于对象属性的定义和访问
const PROP_NAME = Symbol();
const PROP_VALUE = Symbol();
let obj = {
[PROP_NAME]: "NAME"
}
obj[PROP_VALUE] = 233
obj[PROP_NAME] // 'NAME'
obj[PROP_VALUE] // 233
我们经常会需要使用Object.keys()
或者for...in
来枚举对象的属性名
let obj = {
[Symbol('name')]: 'NAME',
value: 233,
}
Object.keys(obj) // ['value']
for (let p in obj) {
console.log(p) // 分别会输出:'value'
}
Object.getOwnPropertyNames(obj) // ['value']
Symbol类型的key不能通过Object.keys()
或者for...in
来枚举
不过我们可以把一些不需要对外操作和访问的属性使用Symbol来定义
当使用JSON.stringify()
将对象转换成JSON字符串的时
JSON.stringify(obj) // {"value":233}
获取以Symbol方式定义的对象属性
// 使用Object的API
Object.getOwnPropertySymbols(obj) // [Symbol(name)]
// 使用新增的反射API
Reflect.ownKeys(obj) // [Symbol(name), 'value']
场景2:使用Symbol来替代常量
const TYPE_AUDIO = 'AUDIO'
const TYPE_VIDEO = 'VIDEO'
const TYPE_IMAGE = 'IMAGE'
function handleFileResource(resource) {
switch (resource.type) {
case TYPE_AUDIO:
playAudio(resource)
break
case TYPE_VIDEO:
playVideo(resource)
break
case TYPE_IMAGE:
previewImage(resource)
break
default:
throw new Error('Unknown type of resource')
}
}
我们经常定义一组常量来代表一种业务逻辑下的几个不同类型,且这几个常量之间是唯一的关系
我们可以使用Symbol来实现
const TYPE_AUDIO = Symbol();
const TYPE_VIDEO = Symbol();
const TYPE_IMAGE = Symbol();
场景3:使用Symbol定义类的私有属性/方法
借助Symbol以及模块化机制,可以实现类的私有属性和方法
// fileA.js
const PASSWORD = Symbol();
class Login {
constructor(username, password) {
this.username = username;
this[PASSWORD] = password;
}
checkPassword(pwd) {
return this[PASSWORD] === pwd;
}
}
export default Login;
// fileB.js
import Login from './a'
const login = new Login('admin', '123456')
login.checkPassword('123456') // true
login.PASSWORD // No!!!
login[PASSWORD] // No!!!
login["PASSWORD"] // No!!!
PASSWORD定义在a.js所在的模块中,外面的模块获取不到这个Symbol,又因为Symbol是唯一的,因此PASSWORD的Symbol被限制在a.js内部使用。以此达到了私有化目的。
注册和获取全局Symbol
在不同window中创建的Symbol实例总是唯一的,如果我们希望在所有window环境下保持一个共享的Symbol,就需要一个API来创建或获取Symbol
Symbol.for()
可以注册或获取一个window间全局的Symbol实例
let gs1 = Symbol.for('globalSymbol1') //注册一个全局Symbol
let gs2 = Symbol.for('globalSymbol1') //获取全局Symbol
gs1 === gs2 // true