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

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

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

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

什么是解构赋值?

解构赋值可将数组的元素或对象的属性赋予给另一个变量,该变量的定义语法与数组字面量或对象字面量很相似。此语法非常简洁,相比于传统的属性访问方式,更加直观清晰。

在不使用解构赋值的情况下,通常我们这样访问数组中的元素:

var first = someArray[0];var second = someArray[1];var third = someArray[2];

使用解构赋值后,代码得到了极大的简化,同时可读性也更强:

var [first, second, third] = someArray;

除了个别特性,解构赋值的大部分特性在SpiderMonkey(Firefox的JavaScript引擎)中都已得到支持,详见 bug 694100。

解构数组与其可迭代性

上面的例子为我们展示了解构赋值在数组中的运用,其基本语法形式为:

[ variable1, variable2, ..., variableN ] = array;

这只是将变量1到变量N分配到数组相应的元素中。当然,如果想在同一时间对变量进行声明,可以在赋值前增加相应的关键字:var,let或const:

var [ variable1, variable2, ..., variableN ] = array;let [ variable1, variable2, ..., variableN ] = array;const [ variable1, variable2, ..., variableN ] = array;

事实上,变量一词用的并不准确,因为解构赋值同样可以用于数组嵌套的情况(注意:左右两侧的格式应保持一致):

var [foo, [[bar], baz]] = [1, [[2], 3]];console.log(foo);// 1console.log(bar);// 2console.log(baz);// 3

此外,左侧的变量列表还可以一种包含连续逗号的形式跳过右侧对应的值:

var [,,third] = ["foo", "bar", "baz"];console.log(third);// "baz"

ES6中,提供了一种将右侧多余的值以数组的形式赋值给左侧变量的语法——“rest“模式:

var [head, ...tail] = [1, 2, 3, 4];console.log(tail);// [2, 3, 4]

无论是访问数组外还是数组中不存在的元素,都会得到相同的结果:undifined:

console.log([][0]);// undefinedvar [missing] = [];console.log(missing);// undefined

注意,数组赋值模式的解构赋值,同样也可迭代:

function* fibs() {  var a = 0;  var b = 1;  while (true) {    yield a;    [a, b] = [b, a + b];  }}var [first, second, third, fourth, fifth, sixth] = fibs();console.log(sixth);// 5

解构对象

在对象中使用解构赋值,允许你为对象的不同属性绑定变量名。这种情况下,解构赋值的左侧部分类似一个对象字面量,对象中是一个名值对的列表,属性名称位于名值对内冒号左侧,变量名称位于名值对内冒号右侧,每一个属性都会去右侧对象中查找相应的赋值,每一个值都会赋值给它对应的变量:

var robotA = { name: "Bender" };var robotB = { name: "Flexo" };var { name: nameA } = robotA;var { name: nameB } = robotB;console.log(nameA);// "Bender"console.log(nameB);// "Flexo"

当属性名称和变量名称相同时,可如下简写:

var { foo, bar } = { foo: "lorem", bar: "ipsum" };console.log(foo);// "lorem"console.log(bar);// "ipsum"

就像嵌套数组可用于解构赋值一样,嵌套对象也可用于解构赋值,并且两种语法还可以结合在一起使用:

var complicatedObj = {  arrayProp: [    "Zapp",    { second: "Brannigan" }  ]};var { arrayProp: [first, { second }] } = complicatedObj;console.log(first);// "Zapp"console.log(second);// "Brannigan"

使用解构赋值访问对象中未定义的属性,将会得到undifined:

var { missing } = {};console.log(missing);// undefined

为对象的属性命名,但未对其声明(缺少var、const或let关键字),会抛出一个语法错误:

{ blowUp } = { blowUp: 10 };// Syntax error

这是因为,JavaScript的语法规定引擎对语句进行解析,需以块语句为开头(例如,{console}便是一个有效的块语句)。解决的办法是将整个表达式包裹在一对括号中:

({ safe } = {});// No errors

非对象、数组、迭代的解构类型

当我们尝试对null或undefined使用解构赋值时,将会抛出一个类型错误:

var {blowUp} = null;// TypeError: null has no properties

但是,对于其他原始类型如:布尔量,数字或字符串等则可以运用解构赋值,并得到undifined:

var {wtf} = NaN;console.log(wtf);// undefined

对于这种情况,你可能会感到很意外。但原因其实很简单,这是因为使用对象赋值模式时,被解构的值必需能够转换成一个对象(object)。大多数的类型都可以转换为一个对象,但null和undefined却并不能被转换。当使用数组赋值模式时,其值必须有一个迭代器。

默认值

对于值和属性未定义的数组与对象,你仍可以运用解构赋值的方式为其设定默认值:

var [missing = true] = [];console.log(missing);// truevar { message: msg = "Something went wrong" } = {};console.log(msg);// "Something went wrong"var { x = 3 } = {};console.log(x);// 3

(编者注:此功能在Firefox上目前只实现了前两种情况,而第三种并未实现。见bug932080。)

解构的实际应用

函数参数定义

作为开发人员,我们经常把一个对象用作函数的参数。这个对象具有很多的属性,以便暴露出更多便于我们使用的API,从而无需迫使我们的开发者去记住大量独立参数的顺序。我们对参数对象使用解构赋值,这样,在访问对象属性时,便可以避免重复调用这一参数对象,示例代码如下:

function removeBreakpoint({ url, line, column }) {  // ...}

这是来自Firefox开发工具JavaScript调试器(在JavaScript中执行)中的代码简化片断。我们发现这种模式是极好的。

配置对象参数

对前面的例子进行扩展,若我们正在对对象的属性进行解构赋值,那么我们仍旧可以为其赋予默认值。这是十分有用的,尤其是当我们打算配置对象或是对象的属性已经有了合理的默认值。例如,jQuery中的AJAX函数需要一个配置对象作为其第二参数,可以改写如下:

jQuery.ajax = function (url, {  async = true,  beforeSend = noop,  cache = true,  complete = noop,  crossDomain = false,  global = true,  // ... more config}) {  // ... do stuff};

这样就避免了为配置对象中的每个属性重复:var foo = config.foo || theDefaultFoo(编者注:不幸的是,在Firefox中,对象简写语法中的默认值仍旧不可使用,详情见bug932080的最新更新。)

ES6迭代协议

ECMAScript6中还定义了一项迭代的协议,在这个系列的前面我们已经谈到过。当你遍历 Maps(一个ES6非标准库),会得到一系列的[key,value]。我们可以对这些[key,value]运用解构的方式,从而方便地访问它们:

var map = new Map();map.set(window, "the global");map.set(document, "the document");for (var [key, value] of map) {  console.log(key + " is " + value);}// "[object Window] is the global"// "[object HTMLDocument] is the document"

只遍历key:

for (var [key] of map) {  // ...}

或只遍历value:

for (var [,value] of map) {  // ...}

多返回值

你可以通过数组的形式返回多个值,并对其解构赋值:

function returnMultipleValues() {  return [1, 2];}var [foo, bar] = returnMultipleValues();

或者,返回的值为一个对象,用解构赋值的方式对其进行命名:

function returnMultipleValues() {  return {    foo: 1,    bar: 2  };}var { foo, bar } = returnMultipleValues();

与上面两种模式相比,下面这种模式就显得过于繁琐:

function returnMultipleValues() {  return {    foo: 1,    bar: 2  };}var temp = returnMultipleValues();var foo = temp.foo;var bar = temp.bar;

或着使用连续风格的传递(continuation passing style):

function returnMultipleValues(k) {  k(1, 2);}returnMultipleValues((foo, bar) => ...);

从CommonJS的模块中导入接口名

不使用ES6模块了吗?仍使用CommonJS的模块?没问题!当导入一些CommonJS的模块时,非常常见的情况是模块的接口功能比你实际需求的多许多。通过解构的方式,你可以明确你需要的那部分,并且可以防止多余的接口名污染你的命名空间:

const { SourceMapConsumer, SourceNode } = require("source-map");

(如果你使用ES6模块,你应当知道类似的语法可用于声明导入。)

结语

所以,就如你所看到的那样,在很多独立细小的方面,解构赋值都非常有用。在Mozilla,关于它的使用我们积累了大量的经验。十年前Lars Hansen将JS的解构赋值模式引入Opera,随后Brendan Eich将他引入Firefox。并在Firefox2中得以应用。

之前,我们说ES6将会改变你写JavaScript的方式。将这些新的特性和微小的改进结合起来,它终将会影响你工作中的每一个项目。这是一场以进化的方式发起的革命。

当然,这是团队努力取得的成果。在这里,特别感谢Tooru Fujisawa (arai)和Arpad Borsos (Swatinem)作出的杰出贡献。关于浏览器的支持方面,Chrome对解构的支持正在开发中,无疑其他浏览器会及时支持。至于现在,如果你想在Web上使用解构,则需要使用 Babel或 Traceur。

原文链接:ES6 In Depth: Rest parameters and defaults

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

相关阅读:

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

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

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

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

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

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

如何用VB创建控件-Delphi资料 生成程序组和项-Delphi资料 实现超级链接-Delphi资料 实战Delphi数据网格色彩特效 使dbgrid的某几笔资料变色-Delphi资料 树形图(Treeview)的使用概述-Delphi资料 透明FORM-Delphi资料 为列表框添光彩-Delphi资料 限制FORM的大小-Delphi资料 用Delphi开发分隔线组件 用Delphi设计拨动、跳线开关组件 用Delphi 设 计 拨 动、 跳 线 开 关 组 件 用Delphi实现JPEG格式图像的显示 用Delphi制作动态有声标签 运行时生成控件-Delphi资料 在DBGRID中实现COPY、PASTE功能-Delphi资料 在Delphi程序的About窗口中建立URL连接 在Delphi中利用Tbatch组件完成数据批处理 在Delphi中巧改窗体文件实现控件数组化 在Delphi中实现不同风格的SPEED和BUTTON 在Delphi中实现类似VB中的控件数组。 在RichEdit中的串查找-Delphi资料 在按钮中快速启动程序-Delphi资料 怎样读出MEMO控件的当前值-Delphi资料 怎样使用Delphi 5中的TExcelApplication操纵Excel 97/2000 怎样在TDataset中汉英混用-Delphi资料 制作可移动的窗体的MovePanel控件-Delphi资料 制作可移动的分割窗体-Delphi资料 制作用于日期时间型字段的DELPHI数据感知控件 制作主窗口显示前的版权窗口-Delphi资料 状态条插入可视控件-Delphi资料 有没有办法让用VC7 build出来的exe文件在VC6下调试? 请问,如何让客户端自动下载安装并注册ActiveX控件(最好能给出详细步骤), 请来说说Rational Rose、PowerDesign、visio这三个软件的功能与异同 怎么在JBUilder7设置命令行??? 电话拨号问题请教 100分 怎样读取数据库中的二进制数据? 急啊~fread的第二个参数忽略回车,怎么办? 为什么photoshop的调色板里只有一种颜色,急,在线 redhat linux8.0中文版有没有中文的帮助文档 Linux Apache+PHP+MySQL的配置问题?? 马上登陆geniusbible.yeah.net网站 我问一个简单问题 各linux都什么优点 这段代吗怎么写? 分乃身外之物,顺便问一个问题。 在delphi中怎么样把字符串的前后空格去掉 有没有人用vss做版本控制的?? 摩托遇到怪事~~决定研究一下~~有兴趣看看拉~~ 求救:哪位有NotesSQL 2.06 email:frank@southsundin.com API ATCS10_SCO505版本,免费的类似TUXEDO消息中间件,欢迎大家使用!!! what is the MAPI? 一个关于子窗体的问题?请大家帮忙,在线等待! 如何做浮动窗体! 一个不是很难的问题。我却很难哟 请教关于访问Jbuilder7中数据库的问题(急) 突然想到的一个问题,请问大家在认真思考问题的时候都习惯做些什么动作? 在SDI程序中,如何在“框架类”中得到“文档类”的指针? 经常看到图片的上传到数据库,以及如何显示的问题,并且在另一个页面实现指定位置显示多个图片!我整理了,需要来登记! 招聘程序员!!!! 各位老大:请帮助!!!!! 请假两天要扣掉薪水的百分之几? JSP通过JDBC连接ORACLE的问题!!! 简单问题,vb得块注视是什么? 为什么mingw和DJGPP. 的主页总是上不去?? 五笔怎么装?装在什么目录下? 最远的距离 请教关于访问Jbuilder7中数据库的问题(急) JSP通过JDBC连接ORACLE的问题!!!!!!!!!!!!!!! 打印机状态,在线等待,万分火急 modelmaker6这东西是做什么的,那位前辈知道 NOTES在用久了之后,邮箱会变的巨大,几百MB,但即使我将邮件删除,其邮件文件还是那么大,怎么可以让它缩小? 我为程序中的职工设了一个序号,人数有多少序号就有多少。可以一眼就看出有多少人。可是当我在离职表中删除职工时。序号跟着被删除。删除 关于sql的难题。 请问如何用SQL语句更改一个表的字段长度,其他都不变. jsp读取oracle8.1.6数据表中的中文,读出为?,着急啊。 上个100帖子已结,现在再拿100分求从导入到数据库的代码,各位老大帮忙看看。 怎样用程序设置文件夹共享? VB中,怎样实现C中的continue? 注册表与记录登录密码 更新表中某字段的值 男友手机存我的电话号码名字只是我的姓,这说明什么问他怎么这样子,他居然说习惯每个人都只存姓,我说同姓的很多啊,那存同音就行啦. 运用公民的政治生活的相关知识,分析实施法律援助的重要意义 it,speak,become,English,that,I,get,the,could,was,I,could,job连词成句 手机里怎么存男朋友的手机号码各位亲爱的姐妹们……你们的手机里是怎么存自己男友的号码的……说出来分享一下……PS:拒绝本名、老公、亲爱的、宝贝等庸俗答案…… 求几句古代的经典诗句!就是和“风萧萧兮易水寒 壮士一去兮不复还” 类似的 诗句啊 I Speak Because I Can 歌词 英语翻译“应客户的要求,我公司此申请案比较赶急,可否麻烦您尽快帮忙处理,”弄错了,汉译英啦,汗汗汗! 女生英文名有叫Angie的么?这个名字好不,怎么读? 用2根长都是16分米的铁丝分别围一个长方形和正方形 英语翻译1st set B/L Consignee:to order of shipperNotify :MO HK- MOHKG will pass the related document to you. Chander是什么意思,怎么读,我想用这个名字当我的英文名合适吗?我是个男的如果不合适,拜托给我起个合适的,我比较喜欢花 月亮 七月 夏天 鸳鸯 之类的,另外我的名字是xiao 起个跟我名字谐音 英语翻译1、Landed fee deliver to the destination place2、Certificate of the material and the certificate of possible treatment of surface 3、How man is the produts you could refund the mold charge? 英语翻译 英语翻译然后翻译成中文I need MP3 players printed in 1 colour with audio loaded onto each unit.重点翻译(with audio loaded onto each unit)这一段,因为这一段不知道如何理解.“是不是要打印“Audio loaded”在每个 第3、4、5题, 英语翻译1.01 Neither Principal nor Agent shall be responsible for the actions of any third parties or associates who may be involved in any activities outlined in this Memorandum.1.01 The Parties have entered into a binding confidentiality or mut 英语翻译和德国一家机构合作,发过来的INVOICE里有2个公司名称,一个是公司名A,但是收款方却是B,咨询对方然后答复““B” is our bank although we are the beneficiary,because we are a public health institution of 3 4题我做的对不对 英语翻译A taper company sends me the sample by there A/C.I did't like the sample then I send the sample to that company by my A/C and he made the same one.Now we are doing great business.I expect the same from you. 英语翻译请真正懂外贸的高手翻译下,如果只是在金山词霸里搜索给我答案就免了.1:20% advance in 3 working days of contract date and 100% pyt of prov invoice immediately on faxing copy of DOCTS after price fixing the 20% de 高中物理竞赛试题 急一质量为m的炸弹一速度v飞行,其内部的炸药产生能量e,使此炸弹分为两半,一半的质量为另一半的k倍.若两半仍能沿着原方向前进,试分别求其速率 运用政治生活的相关知识说明国际为什么重视三峡工程后国家 外贸英语, 请高手帮忙翻译一下 !In respect of the shipment of Iron Ore that does not meet the Fe specifications set forth in Clause 3 the price referred to in Clause 4 shall be adjusted in accordance with Fe content as determined pursuant “你”左边的那个单人旁念什么呢?3Q 今年的橡胶价钱是多少,明年会是什么价位? 王源英文名 诠能组什么词 今年的橡胶价会比去年的好吗? 质量为m绕制均匀的弹簧放在光滑水平面上在其一端作用一水平力F使其平动若将此弹簧一端固定在天花板上,则弹簧伸长的长度比其运动时短为使其长度与运动时相等 在弹簧下端应挂质量m‘= 诠字怎样组词?组一个就够了. 今年的橡胶价会更高吗 王源英文名怎么写 诠换偏旁组词 为什么今年橡胶价格下降这么多 五句形容人一心一意的古诗,求 2,4, 这个地址用英语怎么写?中国山东省济宁市市中区税务街苏州苑小区2号楼东3单元402 一心一意这种形式的词语 请检查1.2.4.5. 英语地址怎么写中国上海市闵行区沪闵路2753号北桥花博园B11 一心一意类的词语比如一心一意 王字旁加个月字念什么字 龙组词,请快点回答 ,第一个我就 我国古代发明较早的化学工艺有A造纸,指南针,制火药,冶炼钢铁 B制青铜器 制火药,印刷术,烧瓷器C制青铜器,冶炼钢铁,烧瓷器,制火药,D冶炼钢铁,指南针,造纸,印刷术 王字加个月字念什么?那为什么字典里没有啊 12月的六级~考完好久了,天天担惊受怕的~求给估分好安心会吧.再不过要疯了,长阅读对9个听力对了13个,填词5个吧,句子都写得不全啊阅读填词2个(这个时态错误那些给分吗)?,传统阅读对5个. 指南针和印刷术是谁发明的·Y 电热地膜的工作原理是什么? 请问一下有人知道word里面怎么打横线字哟? 就告诉我吧打心底感受大伙 i know you want me翻译成西班牙语. 电热水袋的工作原理,及其中的化学药物是什么 拜托大家看下word里面怎么打横线字哟? 就告诉我吧非常感受大伙了 It was because I could speak English that I got the job我想问一下这个句子各部分的结构(成分)分别是什么?这个句子的用法是it作形式主语?还是其他什么用法, 填空题1,3两题 请问一下大家word里面怎么打横线字哟?就告诉我吧谢谢各位了3d It was becauce I could speak English that I got the job.请问句中的that作什么? 填空题第2.3.4题 请问一下大家word里面怎么打横线字哟? 就告诉我吧非常感受大伙了学8 It was beause I could speak English that I got the job.分析句子成分, 请问第3道填空题怎么做?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘