ES6新加了数据类型:Symbol(2018-05-11)
数据类型
在介绍Symbol之前,我们简单介绍一下JavaScript的数据类型:
JavaScript有6中数据类型,分别是:
String 字符串类型
Number 数字类型
Object 对象类型
Boolean 布尔值类型
Null 空值
Undefined 未定义
设计Symbol的初衷是为了解决对象属性名重复
//定义一个symbol类型的变量
let sm = Symbol();
console.log(sm);
//打印结果:Symbol()
console.log(typeof sm);
//打印结果:symbol
我们用一个Symbol( )函数来创建一个symbol类型的变量,我们打印了一下变量sm,得到的结果是控制台输出:Symbol( ),它代表着一个独一无二的值,虽然我们看不到它长什么样子,但基本上,它有点类似字符串。如何判断他是独一无二的呢?
let sm1 = Symbol();
let sm2 = Symbol();
sm1 === sm2 //结果:false
console.log(sm1);//结果:Symbol()
console.log(sm2);//结果:Symbol()
看起来是一样的,但是实际上是不一样的,如何让他看起来不一样的呢?
let sm1 = Symbol('sm1');
let sm2 = Symbol('sm2');
console.log(sm1);
//结果:Symbol(sm1)
console.log(sm2);
//结果:Symbol(sm2)
用字符串sm1和sm2作为参数,结果打印出来的变量sm1和sm2就是Symbol(sm1)和Symbol(sm2),等于加上了描述,很容易区分出来。
需要注意的是,即使参数一样,描述一样,得到的两个值也是不相等的:
let sm1 = Symbol('sm');
let sm2 = Symbol('sm');
sm1 === sm2 //结果:false
当symbol值作为对象的属性名的时候,不能用点运算符获取对应的值。
let name = Symbol();
let person = {
[name]:"张三"
};
console.log(person[name]);
//结果:张三
console.log(person.name);
//结果:undefined
//第一种用中括号的形式[ name ]能正确获取到,第二种用点运算符的形式,获取失败。
属性名的遍历
当symbol类型的值作为属性名的时候,该属性是不会出现在for...in和for...of中的,也不会被Object.keys( )获取到。
//定义一个symbol类型的变量name
let name = Symbol();
//定义一个含有两种类型属性的对象
let person = {
[name]:"张三", //symbol类型
"age":12 //string类型
};
Object.keys(person);//结果:["age"]
for(let key in person){
console.log(key);
}
//打印结果:age
//symbol类型和string字符串类型,我们通过keys( )函数获取到的属性,只有属性age
getOwnPropertySymbols( )函数 获取symbol的key值
Object.getOwnPropertySymbols( ),它会找到symbol类型的属性并且返回一个数组,数组的成员就是symbol类型的属性值
//定义两个symbol类型的变量name,age
let name = Symbol("name");
let age = Symbol("age");
let person = {
[name]:"张三", //symbol类型
[age]:12 //symbol类型
};
Object.getOwnPropertySymbols(person);
//结果:[Symbol(name), Symbol(age)]
Reflect.ownKeys( )函数
获取所有类型的属性,不管它是字符串类型还是symbol类型
//定义一个对象,含有两种类型的属性
let person = {
[Symbol('name')]:"张三",
"age": 21
};
Reflect.ownKeys(person);
//结果:["age",Symbol(name)]
Symbol.for( )函数
根据参数名,去全局环境中搜索是否有以该参数为名的symbol值,有就返回它,没有就以该参数名来创建一个新的symbol值。
let n1 = Symbol.for('name');
let n2 = Symbol.for('name');
console.log(n1 === n2);
//结果:true
Symbol.for( )创建的symbol值会被登记在全局环境中,供以后用Symbol.for( )来搜索,而Symbol( )创建的变量就没有这样的效果了。
let n1 = Symbol('name');
let n2 = Symbol.for('name');
console.log(n1 === n2);
//结果:false
第一行我们用Symbol( )来创建的一个symbol值,按照上述的所说的,它不会被登记在全局环境中;所以,第二行我们用Symbol.for( )去找的时候,是找不到的,找不到怎么办?此时Symbol.for( )会自动创建一个新的symbol值,也就是说n1,n2是不同的两个symbol值了,所以进行全相等比较的时候,会返回:false。
Symbol.keyFor( )函数
返回一个以被登记在全局环境中的symbol值的key,没有就返回undefined。注意这句话的一个关键词:“被登记在全局环境中”,也就是说这个symbol值是被Symbol.for( )创建的,不是被Symbol( )创建的。
let n1 = Symbol.for('name');
Symbol.KeyFor(n1);
//结果:name
上面的变量n1是被Symbol.for( )创建,不是被Symbol( )创建的,所以用Symbol.keyFor( )去找,是能找到的,会返回这个symbol值的key,也就是它的描述:name。
let n1 = Symbol('name');
Symbol.KeyFor(n1);
//结果:undefined
//1、Symbol( )创建symbol值不会被登记在全局环境中供Symbol.for( )和Symbol.keyFor( )搜索;
//2、Symbol.keyFor( )函数在全局环境中找不到对应的symbol,就回返回undefined。