在学习ES6之前已经学过 6 种数据类型,分别是:Object
,Number
,String
,Boolean
,Null
,Undefined
ES6中新增了一种新的原始数据类型:Symbol
1. Symbol 的基本用法
let s = Symbol();
console.log(typeof s) //symbol
2. Symbol 的特点
Symbol 是独一无二的值。
let s1 = Symbol("zsl");
let s2 = Symbol("zsl");
console.log(s1 === s2) //false
console.log(s1 == s2) //false
//s1 与 s2的Symbol值是一样的,而且二个的描述值(description)也是一样的,即便这样s1 与 s2也不相等。
Symbol
不能与其他数据类型值参与运算。
//下面二种写法都会报错
Symbol(1) + 1;
Symbol("ni") + "ni";
3. Symbol 在对象中的应用
let name = Symbol();
let obj = {
[name]: "zsl"
}
console.log(obj); //{Symbol(): "zsl"}
//获取属性值
console.log(obj[name]) //zsl 注意这里用[],不能obj.name
obj[name] = "zc";
console.log(obj[name]) //zc
Symbol
对 对象元素起到保护作用。
let obj={name:'zsl',skill:'web'};
let age=Symbol();
obj[age]=18;
for (let item in obj){
console.log(obj[item]); //zsl web
}
console.log(obj); //{name: "zsl", skill: "web", Symbol(): 18}
这样使用 Symbol
属性能对年龄起到保护作用 ,但是 Symbol
并不是私有属性。
4. Symbol 属性名的遍历
Symbol
作为属性名,遍历对象的时候,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回,Symbol
不是私有属性。
const obj = {};
const foo = Symbol('foo');
obj[foo] = 'bar';
for (let i in obj) {
console.log(i); // 无输出
}
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [Symbol(foo)]
使用for...in
循环和Object.getOwnPropertyNames()
方法都得不到 Symbol
键名,需要使用Object.getOwnPropertySymbols()
方法。
另一个新的 API,Reflect.ownKeys()
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
Reflect.ownKeys(obj)
返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
let obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
};
Reflect.ownKeys(obj)
// ["enum", "nonEnum", Symbol(my_key)]
Reflect.ownKeys()
方法遍历规则:首先遍历所有数值键,按照数值升序排列。其次遍历所有字符串键,按照加入时间升序排列。最后遍历所有 Symbol
键,按照加入时间升序排列的规则