在知乎上看到的一个问题:“ES6中的symbol类型在实际开发中用的多吗?”我之前在学习ES6的时候也有过这个疑问。这个符号是做什么用的?有哪些应用场景?Symbol在实际开发中用的不多。在查看一些类库的实现时,看到了相关的用法。下面分享几个关于Symbol的使用场景。使用Symbol作为私有属性。我最初是从Egg??源代码中了解到这一点的。看一个相关的代码片段://https://img.ydisp.cn/news/20221025/m1fvgsqogm1.jsCALL=Symbol('BaseContextLogger#call');classBaseContextLogger{[CALL](method,args){//...this.ctx.logger[方法](...args);}}在JavaScript中对于privateAttributes,之前常用的一个方法就是命名约定,方法名以_开头。Symbol出现后看到的比较多的场景之一就是用它来建模私有属性和方法。这可以为一些for...in和Object.getOwnPropertyNames()操作隐藏这些属性,但是ES6中的Symbol与强类型语言中的private相比并不是完全私有的,仍然可以通过Object.getOwnPropertySymbols(),即Reflect。ownKeys()操作枚举这些属性以供访问。Hook函数-自定义格式输出使用MongoDBNode.js驱动生成一个id,在执行ObjectId()或newObjectId()时会一直以固定格式输出,如下图:newObjectId("632c6d93d65f74baeb22a2c9")不了解implementation之前,毕竟显得有点玄乎。写一个类实现自定义输出信息怎么办?带着好奇看了下源码实现://https://img.ydisp.cn/news/20221025/vevfcjsnviy.tsObjectId{toHexString():string{consthexString=this.id.toString('hex');返回十六进制字符串;}[Symbol.for('nodejs.util.inspect.custom')]():string{returnthis.inspect();}inspect():string{return`newObjectId("${this.toHexString()}")`;}}Symbol.for(str)就是用字符串的名字创建一个新的值并注册到全局。如果已经注册,则直接返回。和Symbol()的区别简单理解就是调用100次Symbol()会返回100个不同的Symbol值,调用100次Symbol.for(str)会返回相同的Symbol值。Node.jsutil模块实现了util.inspect.custom方法来声明自定义检查函数。我这里的理解更像是一个hook函数,在https://img.ydisp.cn/news/20221025/shcy2flzfvuPR中已经支持了,使用util.inspect.custom作为publicsymbol,无需加载即可在任何地方使用实用程序模块。这里使用了Symbol.for()。面试官:实现一个可遍历的对象Array、Set、Map数据类型在JavaScript中可以通过for...of来遍历。如果面试官说:“实现一个可以for...of遍历的对象”,这个应该怎么实现呢?Symbol提供了Symbol.iterator方法,返回一个迭代器对象。目前Array、Set、Map等数据结构默认有Symbol.iterator属性,而Object没有,如下所示:console.log([][Symbol.iterator]());//对象[数组迭代器]{}console.log((newMap())[Symbol.iterator]());//[地图条目]{}console.log((newSet())[Symbol.iterator]());//[设置迭代器]{}console.log({}[Symbol.iterator]);//undefinedSymbol.iterator是迭代协议标准的一部分:iteratorsProtocol,它定义了哪些值可以被遍历。要成为一个可迭代对象,必须实现@@iterator方法,可以通过常量Symbol.iterator来访问(有没有发现常用的Array类型其实和Symbol有关?迭代协议标准的另一部分是:iteratorProtocol,定义了生成一系列值的标准方式,通过定义next()方法实现,这里不再赘述,看文档,不难理解Symbol.iterator和iteration协议规则来实现一个可以遍历的对象。constrange={start:0,end:3,[Symbol.iterator]:function(){returnthis},next:function(){if(this.start>this.end){返回{value:undefined,done:true}}return{value:this.start++,done:false}}}for(constidofrange){console.log(id);//0,1,2,3}除了Symbol.iterator和Symbol.asyncIterator之外,this在Node.js后端还有一些使用场景。
