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

【探秘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,进行前端技术交流。  

HTML5发展慢热 开发者热情不减 NimbleBit孪生兄弟创始人:最后悔没有专注和扩大品牌 将对Windows形成挑战:谷歌在Chrome OS中默认支持Office 微软的企业社交大动作:Yammer发布移动SDK 谷歌开源Gumbo:纯C语言实现的HTML5解析库 AMD发布APPML源码,构建clMath库 【观察】3个月,每天增加52台,又一家云企业跻身十万台服务器俱乐部 感受华为IT业务的实力 小米雷军:我为什么做红米? GitHub上线Trending功能,帮你轻松找到有潜力的开源项目 如私人秘书:谷歌搜索将变得更加个性化 微软将于10月17日正式发布Windows 8.1 Google推出在线教育C2C平台Helpouts 技术人员组团参加SDCC 2013的十个理由 继BAT之后 第四大巨头是谁 如果传统IT部门真的消亡,你该何去何从? 闪存突袭,混合储存是否已步入黄昏 Cloudera发布Hadoop开源组件Sentry:提供细粒度基于角色的安全控制 我从其他Shell脚本中学到了什么? 10个调试和排错的小建议 机器学习的时代来临,人类应该做点什么? 云端测试破1500万 Testin已为开发者省2亿 智能腕表inWatch:已发售近3600台 Bingo!微软证实Windows 8.1将捆绑安装Skype IBM宣布收购以色列网络安全公司Trusteer 约10亿美元 如何才能运作好一个开源项目? 为什么JavaScript有能力成为未来企业级编程语言? Red Hat CEO:拥抱开源 拥抱克隆 小米手机-HAXLR8on硬件黑客马拉松 开团了! 移动周报:雷军做红米的N个理由 Pangea Software CEO:08年App Store游戏降价大战的真相 有谁知道有什么API函数可以监控某一特定应用程序对系统发送的消息 我的声音程序,为什么 不能播放啊 各位大虾:请问vbscript中二维数组怎么定义?知道的请告诉我好吗?!!! 圆形或其他形状的button 谁能给出在浏览器中不断显示鼠标位置的最简单javascript代码? PHP如何调用VB生成的DLL(DCOM中间层中的类) 如何用WinSock远程控制修改一台电脑的注册表?请高手给个思路或源码,谢谢!高分相谢。 求一曲线拟合的简单高效算法!最好有源码或伪代码! 请解释一下ActiveX控件中的方法和事件有什么区别? 有谁知道如何设置CreateDirectoryEX中的参数 请问在VC6.0中如何把数据文件做进可执行文件中?在线等待...... 编写DLL时,如何获得某一消息的lParam和wParam参数值 数据维护问题,请大家多多帮忙!在线等待! 请问如何取得用户在控制面板的国别设置中所设的国家或地区是什么? SaxException:File "c:\xml\reports.xml"not found MOV large fs:0 1234h是什么东西? 网页上浮动图片怎么做阿?急~~~ 无模对话框 我到底错在哪? 问一个很简单的问题?如何做一个链接到框架页! 这是不是病毒? 新作一系统需要用条形码输入,用asp.net作,需要与条形码输入器的硬件进行交流吗?条形码的硬件选用什么比较好?价格是多少? 请问各位大虾,那里有COM以及COLLECTION对象编程的文章和例程? 一个保存文件对话框的问题 一个很菜的问题,实在不会 sql语句怎么写? 关于服务器端和客户端通信的问题,急,请各位大虾帮忙 error LNK2001: unresolved external symbol "public: char __thiscall bcdtoasc::secondchar(char)" (?secondchar@bcdtoasc@@QAEDD@Z) 文本框的问题 关于 ACCESS 添加记录的问题? 为什么我在数据窗口中的sql语句中使用参数有错误?提示invalid和不完整! 在UNIX下如何编译C++程序 请教一个COM对象创建的问题 如何获取DropDownlist的SelectedItem.Text? lirun(笨笨狗)请进来领分 怎么得到数据库中的id值。 有点痛,不知道是什么病,大家帮忙看看 GOOGLE被中国"冷处理" 请介绍一本好一点的Winsock函数编程的书,电子书或者纸书都可以 关于全局CDatabase; mysqldump备份数据库时总是出错? 谁有http://211.100.6.72的源代码最好有附带的数据库连接说明。200 在2000server上安装oracle的问题,求教! 怎样深层理解delphi的类变量 数据库中日期范围怎么比较? 如何将Access的数据导入SQL-server 散分了,高手请进---.net不能够bug ???怎样在Delphi中对导出到Excel文件单元格进行划线???? 在VB中如何进行程序的数据输入有效性验证? 请上次回答我NT问题的同志进来拿分,上次只给了100 如何学winzip那样,在弹出菜单中增加一个新的项目 “常识”素材 用哲学观点看服装发展史联系马克思主义哲学,看服装发展字数2000 这个图像为什么斜率为负 劳动发展史是理解全部社会发展史的钥匙.用哲学原理解释,(不少于100字) 使SDS-聚丙烯酰胺凝胶电泳具有高分辨率的三个因素是什么 太空里可以做什么实验快 过两点A(-1,3)和B(2,-3)直线斜率K是 SDS-聚丙烯酰胺凝胶电泳和琼脂糖凝胶电泳?比较说明SDS-PAGE(SDS-聚丙烯酰胺凝胶电泳)和琼脂糖凝胶电泳的物质分离原理和特点? y=-x的图像斜率是1还是-1?斜率有负的吗? 过两点A(-2.4)B(-1 3)的直线斜率方程是 童趣 文言文急 在太空中不能做什么实验 1.还原剂的生成———————— ————————2.铁的还原————————3.将生铁脱硫去P降低含C量得钢————————横线是方程式, al与某无机物高温生成单质和某化合物,其中的单质在无色液体中加热生成磁性材料和单质气体去你妈的什么垃圾题 初一文言文(《童趣》)一.多义词之:故时有物外之趣( ) 心之所向( )昂首观之( )然:怡然自得( )庞然大物( )二.(藐小之物) 藐:(细察其纹理) 纹理:(使之冲烟而飞鸣) 求硫酸的msds! 化学中固体化合物加某单质物生成另一液体化合物和单质物的反应有哪些? 最大的昆虫有多大?在那个地区? 急求0.1n硫酸的MSDS谁有.同志们.抗坏血酸的msds有没有,同志们。谢谢 怎样算电动机线圈的匝数和线的大小? 人类了解历史的途径有哪些? 从海水可获得的在常温下为液态的单质是 A镁 B钾 C溴 D碘 电动机线圈怎样绕线最好要有精细图纸! 昆虫最大有多大无 高2,3直线斜率问题已知点A(2,3),B(-3,-2).若直线L过点P(1,1)且与线段AB相交,则直线L的斜率K的取值范围是( )A.K>=3/4 B.3/4 三氧化二铝和矾土有什么不同 最小的而且会飞的昆虫有多大?我想知道,世界上最小的飞虫有多大?我们是不是可以将它看作是一架微型智能飞行器,其精密程度是非人工所能创造出来的,它是大自然的杰作! 直线a//直线b,b//平面α,a不在α内,求证:直线a//平面α发错了,做这题。上面那题不是。a,b是两条异面直线,平面α过a且与b平行,平行β过b且与a平行,求证:平面α‖平面β。 常用的外圆车刀有三种,其主偏角分别为 高一生物要不要背细胞学说建立历程要不要背什么比夏列文虎克施莱登之类的,还是只要背细胞学说的主要内容?如果要背,要背哪些 需要严密证明,很基础,不难!(6)已知直线a、b异面,且平面α过直线a平行于直线b,平面β过直线b平行于直线a.求证:平面α与平面β平行. 如何写语文中的链接材料语文阅读理解中总会有链接材料这一题 怎样才能拿高分呢 请教 高中生物 历史上细胞学说的建立过程.详细但不冗长! 一道高一的立体几何证明题 如图所示的一组图形为某一四棱锥S-ABCD的侧面与底面.已知SA垂直于平面ABCD,求过A且垂直于SC的平面分别交于SB,SC,SD于E,F,G求证AE垂直于平面SBC(本题第一问本是要画 请问75kw电机在660V时电流有多少,升压到1140v电流是多少,用什么公式计算?应该怎样换算呢?请问660v升压到1140v后能不能节电,能节多少?怎样计算 我想660v电流I=P/√3U78%=75/1.732×0.66×0.78=84A1140v电流I 细胞学说的建立过程,是一个——————过程 为什么会产生渗透压 如题,急求过硫酸钠,杀菌剂,叔丁基过氧化氢的英文版MSDS,麻烦帮帮忙, 人体细胞新陈代谢要多久能换一遍 具体多长时间 谁有钛白粉的MSDS文件?求一份,有的话麻烦发一份给我. 常温常压下,只有一种元素的单质呈液态? 人体细胞几天可以完全的换新?人体细胞经过新陈代谢,经过几天可以完成更新成新的细胞呢?一个好的习惯养成需要三个月,一个好人生,需要十年的追逐,那我们整个人换新到底最短需要多少时 要通过什么来理解全部人类历史的钥匙?.理解全部人类历史的钥匙,应当从()A.阶级斗争发展史中去寻找B.生产劳动发展史中去寻找C.地理环境变迁史中去寻找D.政治制度演变史中去寻找 根据题目材料要求设计低年级段语文测试题低年级阅读材料牙齿的苦恼牙齿工作了一天真疲劳,晚上,准备好好睡一觉.不料,小主人又送来食物,命令它们赶快咀嚼.牙齿们只好全体行动,可心中都 人体细胞一天换多少个 过两点A(1,3).B(-5,6)的直线斜率是1)空间点P(1,2,-2)和Q(-1,0,-1)之间的距离是2)若空间两条直线a和b没有公共点,则a.b的位置关系是3)直线5X-4y-20=0在X.Y轴上的截距分别是过两点A(1,3).B(-5,6)的直线斜率是 在形成精子和卵细胞时,染色体减半进入,父母双方不是少一半么?染色体怎样变化? 请问人体细胞多久会全部更新一次?多久呢 我要重新做人 在常温下为液体的单质是什么? 哪里有仓颉字典下载要收词量比较庞大的 人体细胞多长时间更新 什么常见单质常温下是液体? 中国字典中最难写的是什么字? 植物体内的四种组织,从要根本上说都是来自于?A、分生组织的分裂、分化 B、受精卵细胞的分裂、生长分化 C、保护组织的分裂、分化 D、营养组织的分化演变有些人说选A,有些人说选B,头都大 KMnO4在酸性碱性中性溶液中分别变成什么离子? 谁知道哲学的发展史?分析人是用什么的方式在认识世界的?唯物主义哲学是否是支持命运存在的? 2.下表是四种植物分生组织的细胞周期,有关叙述正确的是 植物 细胞周期的时间(h) a时期 b时期 合 计 物种1 10.6 0.4 11 物种2 18 0.5 18.5 物种3 16.5 2 18.5 物种4 10.4 2.3 12.7 A.四种 急求语文素材啊!拜托拜托了 高中生物(关于细胞学说,细胞是通过细胞分裂产生的 为什么不符合细胞学说老细胞通过细胞分裂产生新细胞,为什么符合细胞学说 求植物的基本组织中的机械组织与分生组织的特点(注意简洁明了).
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘