ES6中的Symbol数据类型
在我们所熟知的基本数据类型中,有Undefined、Null、Boolean、Number和String这几种,但是在ES6中有一种会被我们忽略的一种基本数据类型 ——Symbol,接下来我们来聊聊关于Symbol数据类型的那些相关事宜
MDN上这样描述Symbol数据类型👇
数据类型 “symbol” 是一种原始数据类型,该类型的性质在于这个类型的值可以用来创建匿名的对象属性。该数据类型通常被用作一个对象属性的键值——当你想让它是私有的时候。
我们可以将Symbol理解成一种独一无二的数据标识,在初始化时就具备了唯一性的特点,即使我们声明的内容也一致的情况下也是这样
好了!接下来我们来定义一个Symbol类型的数据
let s1 = Symbol();
//我们通过打印发现s1是这样的内容
s1;// Symbol()
// 我们再来检查一下数据类型(这是属于Symbol自己的数据类型)
typeof s1; //"symbol"
接下来我们来给Symbol中定义它本身的一些描述
let s2 = Symbol("Symbol1");
s2;// Symbol(Symbol1)
好了,我们再来验证一下这种数据类型的唯一性
let s1 = Symbol("Symbol1");
let s2 = Symbol("Symbol2");
let s3 = Symbol("Symbol1")
s1 == s2;// false
s1 === s2;//false
s1 === s3;//false
看得出来,即使描述内容一致,两变量是完全不相等的
使用场景分析
场景一:用在对象中来声明某个特殊的key值
我们在声明对象时经常会使用这种方式
let obj = {
name:"tianqiqi",
"age":"18"
}
// 我们可以通过这种方式取到对应的值
obj.name;// "tianqiqi"
obj["age"];// "18"
我们把Symbol的使用加入
const NAME_SYMBOL = Symbol()
let obj = {
name:"tianqiqi",
"age":"18",
[NAME_SYMBOL]:"echo"
}
let n = obj[NAME_SYMBOL]
console.log(n) // "echo"
console.log(typeof n) // "string"
值的我们注意的一点是,Symbol类型的值,在Object.keys()或者for…in这种枚举操作的时候,Symbol类型会表现成为不可枚举的状态,我们来看看
const NAME_SYMBOL = Symbol()
let obj = {
name:"tianqiqi",
"age":"18",
[NAME_SYMBOL]:"echo"
}
console.log(Object.keys(obj)) // [ 'name', 'age' ]
for(let attr in obj){
console.log(attr)//"name","age"
}
通过进行一些遍历的操作,我们发现Symbol不可被枚举,我们可以利用这一点特性,来修饰对象内部不可输出的变量,即一种内部私有属性的定义
如果我们必须去通过遍历取得对象中所有的属性该怎么办呢?可以通过这样的方法去取值
// Object中有几种专门针对Symbol的API
Object.getOwnPropertySymbols(obj);//[ Symbol() ]
// 通过另一个方法能够获取到所有的key值
Reflect.ownKeys(obj);// [ 'name', 'age', Symbol() ]
场景二:一个类中的私有属性
只在模块化场景下生效
//a.js
//声明一个私有变量
const USER_PASSWORD = Symbol()
class Person{
constructor(username , password){
this.username = username
this[USER_PASSWORD] = password
}
//定义一个方法
getPassword(p){
return (this[USER_PASSWORD] === p )
}
}
module.exports = Person
const Person = require("./b.js")
let person = new Person("11","321")
//由此可知在外部无法获取内部定义的私有状态
console.log(person[USER_PASSWORD]) //报错
let res = person.getPassword("321")
console.log(res) //true
最后补充:Symbol数据能够挂载全局供我们使用
const gs1 = Symbol.for('global_symbol_1') //注册一个全局Symbol
const gs2 = Symbol.for('global_symbol_1') //获取全局Symbol
gs1 === gs2 // true