说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

【探秘ES6】系列专栏(八):JS的第七种基本类型Symbols

HTML文档下载 WORD文档下载 PDF文档下载
新一代JavaScript标准ES6正式发布。【探秘ES6】系列专栏将一一剖析ES6的诸多新特性,让Web开发者对此有清晰全面的了解。本文为系列的第七篇,带你了解ES6的Symbols。

ES6作为新一代JavaScript标准,已正式与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解,Mozilla Web开发者博客推出了《ES6 In Depth》系列文章。CSDN已获授权,将持续对该系列进行翻译,组织成【探秘ES6】系列专栏,供大家学习借鉴。本文为该系列的第八篇。 

本期我们要讨论的symbols是个什么东西呢?

这里的Symbols不是指的徽标。

也不是能在代码中使用的小图片。


它也不是代表其它任何东西的一个别名。

当然咯,Symbols和Cymbals(铜钹)完全是两回事。


(在编程过程中使用铜钹可不是一个好主意,吵到你炸!)

言归正传,什么是Symbols呢?

它是Javascript的第七种基本类型

自1997年Javascript被标准化以来,它定义了六种基本类型。直到ES6,JS程序中任何一个值都属于以下几种类型之一。

  • Undefined
  • Null
  • Boolean
  • Number
  • String
  • Object

每种类型都是一系列值的集。前五个都是有限集。当然,Boolean类型只有true和false两个值,而且他们应该不会给Boolean型增加新值了。其它类型的值基本上都是数字和字符串。理论上说Numbers类型有18,437,736,874,454,810,627个值(包括了NaN,NaN是“Not a Number”的缩写)。String类型中可能的值就太多了,我算算大概有 (2144,115,188,075,855,872 − 1) ÷ 65,535个……当然,我这种算法不一定是精确的。

Object是一个无限集,每一个Object都是独一无二的。你随意打开一个Web页面就会生成一大堆新的Object。

ES6 Symbols也是一个集,但它的元素既不是字符串也不是对象。它是ES6的新成员:第七种基本类型。

让我们来谈谈它的应用场景。

以一个简单的布尔型来举例

在JavaScript中,有时候将一个对象中的数据扩展到其它某个对象中是十分方便的。

例如,假设你正在写一个JS库,目的是使用CSS过渡让DOM元素在屏幕上移动。你应该知道同时使用多个CSS过渡在同一个div上是行不通的。这会引起div不规律跳跃。你打算解决这个问题,不过首先你得想法知道这个元素是否正处在一个过渡中。

怎样来解决这个问题呢?

其中一种方式是使用CSS APIs让浏览器来告诉你元素是否在位移过程中。但这未免有点杀鸡用牛刀了。你的库应该存储了移动状态:代码中触发过渡的时候就应该记录了!

你真正需要的是一种方法来跟踪记录哪些元素在过渡。你可以把过渡中的元素存在一个数组中。每当你的库触发一个元素的过渡之前,先检测那个元素是否在数组中。

遗憾的是,如果数组很大的话,遍历起来会很耗时。

在你看来最简单的方法其实是为元素设置一个标识:

if (element.isMoving) {  smoothAnimations(element);}element.isMoving = true;

这样也会有一些潜在的问题。无法避免的事实是代码中会用到这个DOM的地方不止这一处。

  1. 其它代码中如果使用了for-in 或者 Object.keys()会遍历DOM的所有属性(会造成额外性能消耗)。
  2. 一些思维灵活的库作者会从技术方面考虑——你的库与其它库兼容性会很差。
  3. 一些思维灵活的库作者也会考虑扩展性——你的库扩展性也会很差。
  4. JS标准委员会将来也许会为所有元素提供一个.isMoving()的方法,那么你需要重构你的代码,那时候你就傻眼了。

当然,你可以用一个冗长或傻瓜式的字符串来作为属性名,只需确保不会和别的属性重名。

if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {  smoothAnimations(element);}element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;

代码写成这样也太虐待自己的眼睛了。

使用加密方法你可以生成一个理论上唯一的属性名:

// get 1024 Unicode characters of gibberishvar isMoving = SecureRandom.generateName();...if (element[isMoving]) {  smoothAnimations(element);}element[isMoving] = true;

object[name]语法使你可以使用任何字符串作为属性名。所以这样是可行的:不会有命名冲突,看起来还清爽!

但是,这样会导致调试体验糟透了?当你使用console.log()来打印元素的这个属性时,你会看到一大段字符串的垃圾数据。并且,这样的属性不止一个吧?你将如何保持连续性?每次重新加载的时候它们都生成不同的属性名。

为什么要搞得这么复杂?我们要得仅仅是一个简单的布尔值而已!

Symbols可以解决这个问题

Symbols集中的值可以由程序创建和并作为属性的键来使用,也不用担心名称冲突。

var mySymbol = Symbol();

调用Symbol()来创建一个新的Symbol值,它不会等同于其他值。

与字符串和数字一样,你可以使用symbol来作为属性值。因为它不等同于其它任何字符串,这个symbol-keyed属性可以确保不会与其它任何属性冲突。

obj[mySymbol] = "ok!";  // guaranteed not to collideconsole.log(obj[mySymbol]);  // ok!

接下来这方法就可以解决上面我们所讨论的那种情况:

// create a unique symbolvar isMoving = Symbol("isMoving");...if (element[isMoving]) {  smoothAnimations(element);}element[isMoving] = true;

关于这段代码的几个说明:

  • Symbol(“isMoving”)中的“isMoving”被称作描述。它对调试很有用。当你使用console.log()就可以打印出对应的symbol值,如果你想把它转换为字符串(比如说在打印错误信息的时候)可以使用.toString()。
  • element[isMoving]被称作symbol-keyed属性(使用symbol作为键的属性)。从字面意思就可以说明它就是使用symbol作为属性名而不是使用字符串。除去这一点,它和其它属性并没什么区别。
  • 和数组元素一样,symbol-keyed属性不能通过圆点符号来获取值(obj.name 这样是不行的)。它的值必须通过方括号来获取。
  • 通过symbol的值获取symbol-keyed属性值就很容易了。上面的例子展示了如何获取和设置element[isMoving],我们可以判断元素的isMoving状态了,如果有必要的话甚至可以删除isMoving状态。
  • 另一方面,以上的前提是isMoving在当前作用域中。这体现了symbols的弱封装机制:一个模块可以创建几个symbols在对象中任意使用而不用担心与其它模块的属性冲突。

因为symbol键值是被设计来避免冲突的,所以JavaScript最基本的对象检测特性是会忽略symbol键值的。以for-in循环为例,循环只会遍历对象的字符串类型的键。Symbol键直接被忽略过了。Object.key(obj)和 Object.getOwnPropertyNames(obj) 也是这样运作的。但是sysmbols并不完全是私有的:可以使用新API——Object.getOwnPropertySymbols(obj)将所对象的所有symbol键;另一个新API—— Reflect.ownKeys(obj),将会同时返回string和symbol类型的键。(在以后的文章中我们将完整地探讨Reflect API。)

在库和框架中symbols将会有很多用途,不久我们会看到,JS语言本身对它也会有广泛的使用。

symbols确切定义是什么呢?

> typeof Symbol()"symbol"

Symbols和其它基本类型大不一样。

从创建开始就是不可变的。你不能为它设置属性(如果你在严谨模式下尝试,会报类型错误)。它可以作为属性名。这是它的类字符串性质。

另一方面,每一个symbol都是唯一的。与其他的不同(就算他们的描述是一样的)你可以很容易地新创建一个。这是它的类对象性质。

ES6 symbols与Lisp和Ruby中的更传统的symbols很类似,但是没有如此紧密地集成到语言中。在Lisp中,所有的标识符都是symbols。在JS中,标识符和大多数属性的键值的首先仍是字符串,Symbols只是为开发人员提供了一个额外选择。

关于symbols的一个忠告:与JS中的其它类型不同,它不能被自动转换为字符串。试图拼接symbol与字符串将会引起类型错误。

> var sym = Symbol("<3");> "your symbol is " + sym// TypeError: can't convert symbol to string> `your symbol is ${sym}`// TypeError: can't convert symbol to string

你可以通过显示地将symbol转换为一个字符串来避免这个问题,通过String(sym)或者sym.toString()。

symbols的三种形式

有三种方法来获取symbol。

  • Call Symbol()。我们已经讨论过这种方法了,每一次调用它都将返回一个唯一的symbol。
  • Call Symbol.for(string)。这种方法访问一组已经存在的symbol注册表。与通过Symbol()来定一个唯一值不同的是,symbol注册表中的symbols是共享的。如果你调用Symbol.for(“cat”)三十次,每一次返回都将是同一个symbol。在多页面或者单页面的多模块需要共享symbol时,这是很有效的方法。
  • 使用标准中定义的Symbol.iterator。标准委员会自己定义了几种symbols。每一种都有它的特殊意义。

如果你仍然不确定symbols是否对你有帮助,这最后一个章节会很有趣,因为证实了在实践中symbols是很有用的。

ES6的文档中对通用symbols的使用是如何介绍的?

我们已经看过了ES6是如何使用symbol来避免与已有代码命名冲突的。几周前,在关于迭代器的文章中,我们了解了循环(var item of myArray)是从调用myArray[Symbol.iterator]()开始的。我提到这个方法以前的写法是myArray.iterator(),但是加了symbol以后向后兼容性会更好。

现在我们知道了symbols的用法和作用。那么就很容易理解为什么这样做和这样做的意义是什么。

这里还有其它几个ES6使用通用symbols的场景。(这些特性在Firefox中还没实现。)

  • 使instanceof可扩展。在ES6中,表达式object instanceof constructor被指定为构造函数的一个方法:constructor[Symbol.hasInstance](Object)。这表明它是可扩展的。
  • 消除新特性和旧代码之间的冲突。这比较难理解,但我们发现一些ES6的数组方法将会破坏旧网站的稳定性。其它的Web标准也会有类似的问题:仅仅是添加新方法到浏览器中,已存在的网站就会受到影响。无论如何,造成这些不稳定性的主要原因主要是由动态作用域引起的。所以ES6引入了一个特殊的symbol——Symbol.unscopables,这个Web标准可以用来防止某些方法被牵连到动态域中。
  • 支持新的字符串匹配。在ES5中,str.match(myObject)尝试将myObject转换为正则表达式对象。在ES6中,首先检查myObject是否有myObject[Symbol.match](str)方法。现在库就可以给任何有正则表达式对象的地方提供通用的解析类。

所讲到的这几个symbol的应用都不常见,很难看到这些特性本身对我们的日常代码有任何影响。从长远看就比较有意义了。通用symbols是JavaScript对于PHP和Python中的__doubleUnderscores的改进。标准委员会将来会添加新的hooks到JS中,而不会有影响已有代码的风险。

我什么时候可以开始使用ES6 symbols?

Firefox 36和Chrome 38已经支持Symbols了。我自己也在Firefox中试过了,如果你运行的时候有问题,你该知道问谁吧——找我!

为了让那些本身还不支持ES6 symbols的浏览器支持它,你可以使用pollyfill(一段代码或插件,提供了那些开发者们希望浏览器原生提供支持的功能),比如core.js。因为Symbols还比较新,所以它的pollyfill还不是那么完善,详细了解请看使用说明。

接下来的两篇博客,首先会讨论一些我们期待已久的特性终于被ES6支持了,我实在忍不住抱怨它们的姗姗来迟。我们将从两个很古老的特性作为开始(老到几乎可以追溯到编程历史的起源),紧接着讨论两个与之非常相似的特性,由ephemerons提供技术支持。下次还将深入讨论collections(集合)。

原文链接:ES6 In Depth: Symbols

本译文遵循Creative Commons Attribution Share-Alike License v3.0 

相关阅读:

【探秘ES6】系列专栏(一):ES6简介

【探秘ES6】系列专栏(二):迭代器和for-of循环

【探秘ES6】系列专栏(三):生成器

【探秘ES6】系列专栏(四):模版字符串

【探秘ES6】系列专栏(五):剩余参数和默认参数

【探秘ES6】系列专栏(六):解构赋值

【探秘ES6】系列专栏(七):箭头函数

欢迎加入CSDN前端交流群:218126086,进行前端技术交流。  

Cocos2D-X成全球第二大游戏引擎 仅次于Unity 亲爱的苹果,能不能别让应用太廉价? 陈晓影:一位女海归曲折的拓荒故事 IDG李丰:在中国,创业公司最好是一个One Man Company Google Drive新增“保存到Drive”按钮功能 可自行添加 腾讯CDC创始人唐沐加盟小米 总经理陈妍接任 老板我想辞职:因为小米100万元征集一张壁纸 移动周报:GitHub上最火的Android开源项目 免费才是王道:盘点开发者须知的25个免费数据可视化工具 Pivotal获通用电气1.05亿美元支持 或将改变大数据和物联网的游戏规则 大掌门与阿里云和解:云生态系统呼之欲出 刘有涛:恩信科技云计算大潮中扬帆起航 Cloudera释放Impala 1.0:与Hadoop完全整合,各方面完爆Hive 云通讯平台:让你的应用会说话 触宝用户过亿,CEO王佳梁常说的词是“创新” 全国电脑健康日启动 360搭建电脑维修开放平台 C语言实现归并排序 360石晓虹:针对移动Apps的DDoS攻击将成重大威胁 更社交化:谷歌将推出Google Play平台服务 C语言对磁盘文件进行快速排序 传Google已关闭短信搜索服务 PayPal首席安全官:靠密码验证身份即将寿终正寝 DRM你又赢了:其API纳入HTML5标准 豌豆荚王俊煜:洗白白其实是一个计划外的产物 抢Google等巨头生意,纽约大学小伙挖掘并出售自己数据 noBackend:前端优先的开发模式 C、CPP const 详解 三星5G技术获得突破性进展 未来传输速度可达10Gbps 5月14日:1984年美国社交网站Facebook创办人Mark Zuckerberg出生 Chartkick:一行代码即可绘制出漂亮的图表 用友UAP将打造开放平台 建应用商店销售企业级应用 怎样检查硬盘坏道? 有兴趣的可以看看,测一下自己的水平,我公司的Oracle试题二? 关于数据库访问的问题 资源文件的问题,MYBMP1 IS NOT FOUND 有关WINAMP 的问题? 处理字符串以修改数据库 开机显示the secondry IDE channel no 80 cable …… <input type=file name=pic>如何取值,如何设置初始值???? 么样判断一个客户机是否能够连上服务器上数据库,在线等待 在RAVE中如何加上总页数和当前页数? 有缺邮箱用的吗>?现在有了哦,穷人快来啊。。哈哈,我也是其中一个。 请问一个 应用程序登陆SQl Server 时密码的问题? 菜鸟提问! Outlook Express邮件丢失 非典嚣张的日子里的北京(希望惊起大家对SARS的关注)!!! 问一个简单的概念性问题,分却很多.......还可加哦 一个数据映射错误 关于进程通讯的问题 问一个简单的概念性问题,分却很多.......还可加哦 哪里可以找到关于OA方面的资料?越多越好,100分送上 高手请进,怎么监测到一个文件将被覆盖 请问如何屏蔽F1查看帮助的功能? 高手请进,怎么监测到一个文件将被覆盖 能提供解码器么? 在tdi中,怎样获取封包ip头? 神啊!救救我吧!!!!(在线等待) 我看SARS危机 求助 我该怎么办??? 管理登陆问题解决?? 一个简单的问题,如何对字符串进行减操作? 谁用过struts,进来交流一下! 请大侠看看俺的小程序,哪里错了(关于不规则图形填充) delphi查询问题(急需) 急求:从硬盘安装windowsxp时电脑出显不能安装,找不到eula!如何解决? 系统分析员VS博士 C#连接Oracle? 关于<BASE> 那里有WebDB下载啊. 在ListCtrl里加类似Combo Box的东西,能实现吗? windows2000下vb的一个小问题~~ 如何把当前路径加入查找路径中?立即给分! 对选用不同的纸张大小,在预览中能看出效果吗? 请问怎么在PB6.0中实现Foxpro(*.dbf)的数据导入,到ASA库中 j2me里怎么才能实现图象的滤镜效果?waiting... CDbSet m_dbSet(NULL)在哪一步才能得到一个CDatabase对象的错针? 新手提问:“镜象”是什么意思 求教,如何配置使性能达到最佳,详情见文 怎样在广域网中提高传屏响应速度?帮帮忙!急啊. 在文件钩子当中如何判断是打开文件操作,还是创建文件操作 怎样在applet程序中显示一幅jpeg图片?该图片存在于c:\image\下。 怎么中云母长什么样?它怎么辨认?和白色的河砂小颗粒如何区分? “协议草案”的英语是“draft agreement”还是“agreement draft”?为什么? "截距相等"用看符号吗 河砂中云母怎么辨认?怎么中云母长什么样?它怎么辨认?和白色的河砂小颗粒如何区分? 怎样区别agreement和contract? 两直线平行是截距相等么 石家庄那需要云母,云母沙,河沙,蛭石? 我想问问招远金矿和山东黄金集团哪个好些? 氧化性Al3+>Mg2+>Na+,则元素金属性顺序? 我想知道有多少知名模特被潜规则过?请举例,最好是30岁以下, 山东招远金矿因开采造成的生态破坏 1摩尔C17H18最多与几摩尔氢气发生反应 模特界的潜规则我想当一名男模,我想选一模特公司的,得知要交包装费,而且确切的说那是一家真公司,只是不知道以后为了自己有更好的发展和上台机会,还用不用送礼之类的,还有那谢我不知 金矿在招远的分布 这个物质最多能和几摩尔氢气发生反应?生成什么?为什么? 什么是复合胶乳 招远金矿事故我最大的难题就是看不到你,得不到你的消息我烦的不行 第二个问是什么意思,截距表示什么. 天然胶乳是什么? 如何证明π是圆周率? 二次函数的截距是什么意思?怎么算还有公式啥的,求详细解释!谢谢! 什么是胶乳接枝插层法 在图书馆前站着的那些人是谁?Who are the persons ____ ____ standing in front of the library? 云母屏风烛影深的意思是什么? 包有过氧化钠粉末的脱脂棉上滴水,为什么?脱脂棉燃烧 胶乳的分散稳定性与什么有关 accord,pact,treaty,compact的用法与区别如题,不要到网上copy别人写的那些没有用东西.如果有用我也就不发贴了.下面我再发一下此4个同意词各自的英文注解,都出至Longman当代词典第5版.accord---a formal 说明方式中什么是作诠释?举例 “鬼”是磁场吗我在视频网看了一个关于灵异的节目,科学家说鬼可能是一种磁场或者说脑电波之类的,各位网友能谈谈自己的想法吗?太迷信的不要 想做离子色谱 不知道样品怎么处理 能做吗 用脱脂棉包住Na2O2粉末,往上面滴水,观察到脱脂棉剧烈燃烧起来,可得Na2O2与水反应的结论有哪两个 蝴蝶为什么爱在灯下飞撞 有人用上海精科的万分之一电子分析天平么?效果怎么样我先买了一个沈阳龙腾的,计监局来检了一次不合格,换了一台,还是不合格,10g的砝码称出来9.9983g.计监局的说需要重新选个品牌,谢谢( 这是什么花 招远黄金节在哪举行啊 听人讲.中药也会有重金属成份? 云母断口的形状 过点P(1,4)作直线与两坐标轴正半轴相交,当直线在两坐标轴上的截距之和最小时,求此直线的方程.请用截距式求解 降解中药材重金属含量的方法 market与shop有什么区别?一直没搞明白 第3小题,为什么 |b|0呢,还是x>=0呢,为什么 品种 莲的美食和药用 莲的名胜古迹 莲的诗文、故事、传说 螺纹钢材价格每吨多钱?螺纹钢最新价格? 截距相等是否在符号上也要一样?比如都是正才相等,一正一负不算相等? 你和什么交往作文100字要速度啊!要在这2天内写好啊!字数不要太多100字就好就100不要多也不要少! 数学中何谓纵截距 李阳在家中吃饭时对厨房里的一瓶醋产生了兴趣,他很想知道醋的密度,于是找到了如下器材:小铁块(密度已知为ρ铁)、细线、弹簧测力计和一只足够深的水杯,他利用学过的知识,测出了醋 云母是什么 什么是自然界的蝴蝶效应 云母特性有哪些? 关于股票市场上market maker和dealer的疑问求教股票市场中market maker(做市商)和dealer(不知道中文怎么翻译)的区别.他们是一个意思吗?还是包含关系或者被包含关系?求dealer在股票市场上的准 山东招远怎么样 云母的特点有哪些? 股票交易中的摆单子(limit order)和打单子(market 请解释的浅显易懂摆单子平价交易也能赚手续费吗?这个钱是哪里来的? 山东招远的金矿有哪些能具体的说 招远 金矿的名字 人大代表建议的写作格式 在装饰行业里黄砂一定用河砂,河砂是什么味道? "agreement"和"contract"有什么异同点?I don't need MAYBE,by the way.我再自己多查查. H3AlO3,CH3COOH,C6H5OH,H2CO3,HCO3-酸性排列顺序,还有其水溶液的盐碱性排列顺序.什么什么盐类水解啦之类的,总是记不住.求大神简便的记忆方法,求理解. 经济观察:中国化解产能过剩并非简单“打造两岸经贸合作升级版 ECFA后续美媒:失业者重找工作需要做的五件事外媒曝查尔斯不想当国王 王位或将越代美媒:中国能成为生物技术领域领导者吗美霸主地位逐渐丧失 “去美国化”引争港媒:华人强烈抗议“杀光中国人”言论俄外长与联合国叙问题特使讨论筹备叙问联合国-阿盟叙特使称伊朗应参加叙问题法国正式要求美国停止监听行为 希望低中国养老困局难解 老人:不知十几万够求同存异破壁垒 两岸携手打造中华文化日本欲解禁武器出口 妄图“一箭三雕”美媒:中美日竞争转向拼经济 争亚洲“日媒:美国家安全局曾请求日本协助监听美国海军基地发生枪击案 两人受伤凶手聚焦去美国化:是否为世界多极化发展必联合国-阿盟叙特使称伊朗应参加叙问题“绿色和平”成员登埃菲尔铁塔 悬空表俄外长与联合国叙问题特使讨论筹备叙问解密以色列版007:最爱暗杀 钟爱炸普京签署法律:在克里米亚设立赌博区以德国法庭判决有医疗需求病人可自己种大甘肃阴雨“低温”迎“大暑” 局地须防海外华裔青少年“中国寻根之旅”夏令营高温范围缩小 中央气象台解除高温预警台风黄色预警:“麦德姆”明晨进入江西杭州闹市群租房突起大火 吵嘴后女子烧组图:火爆战国红 哪类最值钱?受台风“麦德姆”影响 G55、G16河北省十二届人大九次会议举行第二次全河南百余法院开“网店” 4月卖出4.中国对外国礼盘点:日趋流行化,形象更苍南泰顺降雨超30毫米 浙江仍有32饥饿猎豹从水中“提溜”出一对乌龟【组普京参观俄“进步”航天火箭中心郑州16家房地产公司违法被罚百万元 以军继续对加沙地带进行空袭 现场浓烟新疆木垒哈萨克自治县庆祝成立60周年离奇判点+罚进被吹 绿地2-1延边曲广州便衣民警公交车上抽查行李暑期赢家输家盘点:骑士喜夺詹皇 热火
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘