ES6学习之路~~Symbol:独一无二的值类型
1. js有多少种数据类型?
同学们异口同声的回答:6种。 那对不对呢?在ES5及以前,是对的。但是,注意啊,现在已经是ES6正式发布两年后了,要回答7种! 至于除了:undefined、null、string、number、boolean、object这六种之外的第七种呢,就是这节我要详细述说的symbol类型了。 我们先来验证下,在谷歌控制台输入下面的代码看看:
let s = Symbol();
console.log(s);
typeof s;
Symbol数据类型是怎么申明的?
先不管这个数据类型有什么用(既然能通过ES6,就不用质疑其作用啦),先来看看怎么才能用出来(在支持ES6,例如谷歌控制台运行下面的代码)
let s1 = value;
let s2;
let s3 = null ;
<!-- 以上,常见的申明方式并不能申明出symbol类型 -->
let sym = Symbol();
let sym1 = Symbol();
let sym3 = Symbol(s1);
<!-- symbol值比较 -->
console. log (sym == sym1);
<!-- symbol型变量赋值 -->
let ev = '' ;
typeof ev;
ev = sym1;
console. log (ev, ' / ' , typeof ev);
console. log ()
ev + 11 ;
ev + 'aa' ;
let symStr = sym3. toString();
console. log (String (sym3));
console. log (Boolean(sym3));
申明很简单,通过Symbol()函数生成即可,并且生成的数据是绝对不等于除自己外的任何一个Symbol值
Symbol类型数据的特点
从上面的代码,可以看出:
symbol值 有自己的数据类型 symbol值 绝对不等于除自己外的任何一个Symbol值,即symbol值是独一无二的 symbol值 不能直接做数值相加和字符串拼接等 symbol值 可以强转为String型和Boolean型的值 根据这些特点,我们再来讨论下Symbol值的作用吧
Symbol类型数据的作用
作为对象属性名,可以保证不会出现同名的对象属性,能防止耨个键被不小心改写或覆盖。symbol值作为对象的属性名使用时,必须放在[]内部(ES6中,增强的对象属性写法),不放在方括号中的写法只适用于字符串属性名
var symKey = Sym();
var a = {};
a[symKey] = 'hello';
var a = {
[symKey]: 'hello'
}
var a = {};
Object.defineProperty(a, symKey, { value: 'hello' });
a[symKey]; // 'hello'
var a = {};
a.synKey = 'hello';
a[symKey]; // undefined
a['symKey']; // 'hello',因为 对象.属性名 的形式只适用于字符串属性名
symbol作为属性名的对象属性名的遍历
symbol值属性名在遍历对象时,不会出现在for…in、for…of循环中(只能遍历字符串类型的属性名称),但symbol值的属性也不是私有的属性,有一个Object.getOwnPropertySymbols(obj)方法返回一个数组,成员是当前对象的所有Symbol值的属性名
var a = Symbol('a' );
var b = Symbol('b' );
var objSym = {
[a]: 'aaa' ,
[b]: 'bbb' ,
c: 'ccc' ,
d: 'ddd'
}
var symPorpertys = Object .getOwnPropertySymbols(objSym);
console.log(symPorpertys);
for (let ii in objSym) {
console.log(ii);
}
那,能不能有个方法可以返回所有的键名呢?当然是有的,Reflect.ownKeys(obj)方法
var a = Symbol('a');
var b = Symbol('b');
var objSym = {
[a]: 'aaa',
[b]: 'bbb',
c: 'ccc',
d: 'ddd'
}
console.log(Reflect.ownKeys(objSym));
for(let ii in Reflect.ownKeys(objSym)) {
console.log('属性名:'+ Reflect.ownKeys(objSym)[ii]);
}
以symbol值作为属性名的属性不会被常规方法遍历得到,因此可以利用这个特性为对象定义一些非私有但又只希望只用于内部的方法
怎么根据symbol(‘xxx’);去找有没有对应的symbol值?这里引入一个新的API:
Symbol.for(),返回值为一个symbol值,同Symbol()方法,不同之处在于已存在的Symbol值使用Symbol.for()不会产生新的Symbol值,而是返回之前存在的Symbol值,而Symbol()每次都返回完全不同的Symbol值
var ss1 = Symbol('ss' );
var ss2 = Symbol('ss' );
ss1 === ss2;
var sf1 = Symbol.for ('sf' );
var sf2 = Symbol.for ('sf' );
sf1 === sf2;
Symbol.keyFor(‘xxx’)方法返回一个Symbol.for(‘xxx’)方法申明的Symbol的key,用于Symbol()申明的Symbol值,则返回undefined
var s1 = Symbol('s' );
var s2 = Symbol.for ('s' );
Symbol.keyFor(s1);
Symbol.keyFor(s2);
Symbol.for()为Symbol登记的环境为全局环境,可以在不同的iframe标签中被Symbol.keyFor()得到