ES6 Symbol标识符对象
2017-03-24 00:31

Symbol标识符

Symbol其实就是一种特殊的字符串。用做对象或者数组的key值。并且它是唯一的,有点类此uuid。

var sym=Symbol();
var sym=Symbol("mooshine");

这个代码用来创建一个Symbol,第二种创建方式中的“mooshine”字符串,只是用作对Symbol的描述,对于创建并没有任何影响。

Symbol每次调用都是创建一个新的Symbol,不会出现重复的情况。

var sym=Symbol("mooshine");
var sym2=Symbol("mooshine");
console.log(sym==sym2);
//false

即使用相同的标识符创建的Symbol也是不同的。

JS系统中提供了一些内置的Symbol。例如:Symbol.iterator,Symbol.match,Symbol.hasInstance,Symbol.split,Symbol.species等等。这些内置的Symbol各有特殊的用途,比如Symbol.iterator用来遍历集合,Symbol.species用来在class中返回父对象的类型。这些不用管,只要知道Symbol就是一个不会重复的key值就可以了。

var sym=Symbol();
var sym2=Symbol();
var sym3=Symbol();
var obj={
    [sym]:"mooshine",
    sym2:"sunshine"
};
obj[sym3]="stars";
console.log(obj[sym]);
//mooshine
console.log(obj[sym2]);
//undefined
console.log(obj[sym3]);
//stars

上面的代码展示了Symbol作为key值的使用,调用一定要使用[]方括号。属性定义,作为key值,在obj定义中也一定要加[]方括号,这里的方括号依赖于ES6中的另一个新特性:属性名的可计算性。用方括号,就表示是可计算的变量。而sym2,会被识别成字符串“sym2”,所以第二个console为undefined。第三种定义方式不用讲,就是属性名的定义。

第一种写法中一些开发工具中会报错,不用担心,那是开发工具还没有支持这种写法。

blob.png

上面是我只webstrom10中的书写情况,webstorm10就不支持这种写法的检查,所以会提示错误,但他在支持的浏览器中是可以运行的。

Symbol属性在for...in循环中是遍历不到的。使用Object.getOwnPropertyNames()方法也是获取不到的,要使用Object.getOwnPropertySymbols()方法来获取Symbol的属性。而且注意,使用JSON.stringify()方法时,Symbol的属性也会被忽略。

 var sym=Symbol();
 var sym2=Symbol();
 var sym3=Symbol();
 var obj={
     [sym]:"mooshine",
     [sym2]:"sunshine",
     [sym3]:"star",
     name:"test"
 };
var names= Object.getOwnPropertyNames(obj);
 console.log(names.join("-"));
 // name
 var syms=Object.getOwnPropertySymbols(obj);
 syms.forEach(function(key){
     console.log(obj[key]);
 });
 //mooshine
 //sunshine
 //star

上面的代码展示如何获取Symbol的属性。注意一点Symbol对象不能转化成字符串,不能和字符串进行+号连接。这样会导致报错的。

Symbol()+"";

blob.png

浏览器会报类型转换错误。

上面通过Symbol()创建的对象,不具有全局特性,跟通过var创建的对象一样,只在创建的上下文,作用域链中可用。

Symbol对象还提供了在全局创建Symbol对象的方法。这个有点类似windows系统的注册表功能。它是在浏览器中全局对象也维护一个注册表,用来保存全局的Symbol对象。这个全局Symbol操作有两个方法:Symbol.for(),Symbol.keyFor()。

Symbol.for()方法会在全局注册表中查找带有某个描述字符的Symbol,找到就返回,找不到就先创建后返回。

Symbol.keyFor()方法用来对全局中注册的Symbol查找对应的描述字符。

var sym=Symbol.for("mooshine");
//第一次创建
var sym2=Symbol.for("mooshine");
//第二次查找返回
var sym3=Symbol.keyFor(sym2);
//查找Symbol的描述符
console.log(sym==sym2);
//true
console.log(sym3);
//mooshine

全局的Symbol是都有描述符的,描述符是全局Symbol注册表中的key值,通过key值来查找对用的Symbol,也可以通过keyFor方法根据Symbol查找对应的描述符。

Symbol的讲解到这里就结束了。说到底它就是一个不会重复的属性名,觉得不会冲突的属性名。那么他到底有什么用呢?在js内部,Symbol.iterator用来实现遍历,Symbol.hanInstance用来实现instanceof功能,因为Symbol不会重复,就不会跟开发者定义的属性名冲突。而我们使用Symbol有什么好处呢?至少现在来看,除了能消除一些命名冲突外,没发现有什么大的用途,倒是规矩不少,理解挺绕。而且对于全局的Symbol来说,要想共享,还是通过描述符的字符串key值来获取的,同样还是会有冲突的。不过,这些说到底还是新东西,新东西在于发现,还是要先掌握,在使用中发现他的更多用途。毕竟这个Symbol是借鉴其他语言已经有的特性来扩展javascript的特性的。

原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(2701)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1