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

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

IBM斥资12亿美元,全球大规模扩建数据中心 “Careerfocus之夜”2014年新春客户答谢晚宴在京举办 Google蚕食了维基百科的访问量? 微软Surface Pro 2 的成功之道 精简代码,为网站减负的十大建议 应用宝逆袭上位 将重构腾讯移动应用分发体系 eBay基础设施的成功经验,我们该如何复制? 自定义富媒体广告:NativeX SDK 5.0发布! WunderBar:零硬件开发基础也能接入物联网! 深入解析:分布式系统的事务处理经典问题及模型 从世纪互联、华云数据和金石易服的发展服路径观察IDC产业发展 SA:2014移动运营商、终端和应用十大关键趋势 使用modern.IE来设计更现代化的网页 全国顶级域名根服务器21日下午疑遭黑客攻击 影响巨大 苹果下一代iPhone的十大预测 《近匠》第07期,专访《恶魔塔防》团队,看俄国复杂深奥的游戏文化 代码托管网站GitHub的总裁和CEO进行职位互换 使用Chromebook的五个指南 云中游终极声明:热酷侵权,有种正面回答少打太极 背后故事:英特尔Edison中国研发 内部评审中曾三次被拒 全栈工程师会是未来的发展趋势吗? 大数据整理:囊括分片、存储方法、扩展等多个方面 物联网 ,下一个云计算市场 一位数据挖掘工程师眼中的“大数据与企业的数据化运营” 揭开“iOS in the Car”的神秘面纱 与Apple对峙:法律途径,并非是我想要 Halfbrick新作市场表现低迷:前作辉煌难续 专访豌豆荚:融资,会给技术团队带来哪些影响? 前端开发必备 40款优秀CSS代码编写工具推荐 新环境下的新体验是互联网硬件火热的根本原因 信息安全救星 ——变形代码产品ShapeShifter 好啊好啊!大家欢迎!啪啪啪啪啪!(赠分50,进来有分啊) 倡议:不管提的问题有没有解决,一段时间后把分都给掉! 登陆后,怎么看不到分数了? 在控件的事件中将控件Free了行吗? corba在delphi6中无法运行 我胃口很大!!! VB能允许运行多大程序才不会出错? 哪里有D版,到哪里能买到D版的??? VB如何插入汇编程序代码?“=ASM:”吗?怎么用? 如何解决读英文书开头难的问题? 有没有打印Tdecisiongrid的孔件 日记 情归何处?? 谁知道哪里可以弄到这本书"Windows Graphics Programming: Win32 GDI and DirectDraw" 程序员杂志第7期的程序擂台目前为止只有一个人做对了 分数不高,还请各位DX们指点以下:如何用DELPHI控制excel的格式(比如第一列的宽度,第五行的高度),以及如何在WORD中生成表格,其中填入数据库的数据. 各位情感高手请解答(没有谈过恋爱的免谈) 一个list控件,style设为checkbox,要怎样才能使列表中各项的默认值是选中状态,也就是说各项一开始都是打了勾的 阿虎菜问7:请问C与C++中的内封函数应该差不多吧? s_cube(竹子), s_cube(竹子)~!! 我爱你,s_cube(竹子) s_cube(竹子) ~!在哪里 简单问题(1) 如何不运行编译? 有谁知道怎么从perl里调用一个c库里的函数????????? 请问在CB中如何隐藏WINDOWS的任务栏呢? 今天不爽,下班后打星际,大家一起来。 指点!在PB中怎样用程序作成一张动态的交叉表 编辑控件怎样才能显示那些怪字符? 有没有人喜欢郑智化 大家推荐好听的几首歌吧! 请教:怎么学c++? 高手点拨! 各位网络高手.如何在程序里讲ip地址转化为域名 有什么方法,可使表单内的组件背景变成透明的而文字不透明,请看例子: 编辑控件怎样才能显示那些怪字符???? swall(壹心) 你还在深圳特区吗? 如何设置Session的密码?请高手指点迷经^^^^^ 哪位可以解释一下下面的代码? perl 的人气太差。罢了罢了。找本perl自己搞定 MsSQL7.0 当日志文件大小未限制而变得很大时,怎样清日志文件,使其减小? 请教诸位牛兄牛姐牛夫人---有难度哦(着急出活!) 基本问题:如何将一个.txt中的内容读入到内存再从内存中读出并存为另一个文件?谢了先!!!! 高手帮帮忙!!!!!!!!!!!!!! 又有台风了。。。。 在zip包中加入ASP推荐的PAD File有用吗????? PB连接SQL数数库,为什么显示的表会不全 如何把一个文件file.dat里的数据写入软盘0磁道0磁头1扇区. 我要骂人! chris2001(牛虻),不是东西 华为工程师 谁知道 vb 的序列号?????? VS.NET 有开了个新铺子。为什么我的ejb/j2ee还没有开张。气愤。 老大们:我是菜鸟,有问题要问,不过不要笑我。一定给分的 体温计和普通温度计的主要区别是什么? 测人的体温的温度计除了水银温度计和电子温度计,还有其他的么? 把一根温度计浸入热水中,温度计的水银为什么先下将后上升 什么是贝克曼温度计的基点温度 我自制了一个30度恒温箱,试验要求温度精确,我采取的是电子控温器,箱内用电子温控探头,为了保险我又放了一支水银温度计在箱内,同时把电子温控探头和水银头绑在同一位置,但读出的结果 怎么样正确使用水银温度计可以手拿另一头给宝宝试热吗?可以放在她的脖劲下试热吗? 贝克曼温度计和接触式水银温度计一样吗? 水银温度计准和电子温度计哪个比较准? 水银温度计在使用中有哪些缺陷 贝克曼温度计多少钱一支? 水银温度计和电子温度计到底哪个准?最近一直看温度,心里有很多的憧憬……但是今天发现一件事,我一直是用水银温度计在量自己的口腔温度,今天早上水银温度计量的口腔温度是36.9(因为 太空中能否使用水银温度计失重状态下能否使用水银温度计 一种温度自动报警器的原理图,在水银温度计里封入一段金属……………一种温度自动报警器的原理图,在水银温度计里封入一段金属丝,当温度升高时,水银面____当温度达到金属丝下端所 用水银温度计测量液体温度,在温度计示数上升的过程中,水银的密度将 ▲ (填“增大”、“减小”或“不变”).我知道答案是减小,但物质密度不是物质本身的性质么?和质量,体积无关么? 水银温度计宝宝刚才把水银温度计放在嘴里咬碎了 我晕 不知道有没有吞到嘴里去 怎么办啊 急 有一种温度自动报警器,在水银温度计里封入一段金属丝,当温度达到金属丝下端所指的温度时电铃就响起来发出警报信号,请说明它的工作原理. 用水银温度计测量液体的温度是正确的方法是什么? 用水银温度计是因为水银是. 水银温度计和电子温度计哪个准啊同一时间把水银温度计和电子温度计在口腔中测量出来的数值不一样,到底要看哪个的啊水银36.4 电子35.8 (差了6度诶)电子温度计我是买【东阿阿胶阿华医 在常温时,将水银温度计插入下列某种液体中,取出温度计放置在空气中后,温度计的读数先升高再降低,则可推断温度计插入的液体是A.食盐水 8.酒精 C.浓硫酸 D.浓盐酸为什么?水银温度计 水银温度计怎么测都看不见有水银啊是新买回来的我之前买了几个都是看不见有水银怎么回事啊 水银属于液态还是固态?水银可流动但又是液态金属,说他完全是液态也不行,那他到底是什么? 为什么蒸馏实验的时候温度计水银球要放在蒸馏烧瓶支管口?放在其他位置有影响吗那为什么在这种东西没蒸发完时,温度计示数会上升,我觉得在这种东西蒸发完之前温度应该是恒定的啊 水银温度计怎么看 水银的固态与液态 比较水银的固态 与 液态 比较 哪个重点啊?在同体积下 在蒸馏装置中,温度计水银球的位置应在何处?为什么? 怎么看水银温度计 水银温度计里的水银是液态的还是气态的谁知道 蒸馏实验时,温度计的水银球应放在蒸馏烧瓶只管口处.哪错了? 怎样看测试体温的水银温度计的水银有没有跑出来? 水银是液体还是固体呢?为什么打碎以后是固体的球状物呢?后面的问题也要回答的哦 蒸馏实验时温度计水银球不放在冷凝管口,如果偏上偏下各有有什么影响那么温度计怎么控温呢?放上放下温度不都是一定的吗~跟蒸馏出来的产物有什么影响呢? 水银温度计怎么看求图 汞是属于固体还是属于液体 蒸馏装置中,温度计的水银球应位于什么地方?作用是什么? 已知湿球温度和干球温度,大气压强,如何求含湿量d?如题,应该在焓湿图上查得出的,我想知道怎么查,不要公式,因为不知道定压比热没法算.求解!我只记得查相对湿度为100%的那条线,但是按干球 温度计里为什么要用水银? 水银温度计在装热水的杯子里爆了偶然,老婆把水银温度计放在有时炒菜时加水的杯子里,当时里面装的开水,结果温度计爆裂了,家里老人家觉得没什么就倒到下水道去了,然后只是用洗洁精清 什么是湿空气,含湿量和相对湿度的定义是什么? 在太空中使用水银温度计.貌似答案是可以.但是还是有点怀疑,我是这样想的.气压低的话沸点低 .那水银不会沸腾么.0.0 还有看过好多人讨论真空下水到底会不会沸腾,好像都没什么结果.请问有 为什么水银温度计放在热水里,示数会先下降再上升?玻璃泡的变化会那么明显吗?有没有什么资料可以找给我看一下? 如何根据空气温度、相对湿度计算含湿量g/Nm3?例如:空气温度32度,相对湿度83%,如何计算g/Nm3?通常可知含湿量为25.22g/kg,请问如何折算成g/Nm3?谢谢了,Nm3是指标准立方米(1个大气压,20摄氏度), 水银温度计碰破后,为什么可用硫粉覆盖是因为贡和硫反映吗? 将一支灵敏温度计的玻璃泡浸入热水里,并立刻观察温度计细管里的水银面的高度变化,将会看到温度计中水银面下降,然后再上升.试说明其道理. 已知温度 露点 气压 求相对湿度 温度计的水银球破裂后,掉在地上的水银能用硫粉除掉吗?换句话说,硫能和水银(汞)能反应吗?如果能反应的话,我想问问硫相对于汞有什么作用?希望前辈们给予详细的解答! 将一支灵敏温度计的玻璃泡浸入热水中,为什么细管内的水银面先下降再上升? 关于干球温度计,湿球温度计的问题我有一个疑问,假如湿度越大,那湿球温度计所沾上的水分就越多,那么蒸发的水分就越多,吸热,制冷就越多,湿球温度计的示数就越小,干湿度差就越大,那就相 汞制温度计打碎的处理除了硫粉还有其他方法吗?我想知道对于汞,有哪些相对便宜的材料能迅速处理汞,请注意要求:迅速,低廉.另外,温度计现在有哪些种类?哪种用的比较多?有哪些可以或者 两只内径不同,下面玻璃泡内水银量相同的合格的温度计,同时插入一杯热水中,过一会儿则看到( )答案是(D)为什么呢?A.两只温度计水银柱上升的高度相同,示数相同 B.内径细的温度计水 如何根据空调冷凝器的空气进口干球温度计算出空调的冷凝温度手头上现有一台冷凝器的换热器,各个尺寸参数都已经知道了.现在要对该换热器做实验,按照国家标准,空气进口干球温度取35度, 为什么水银温度计碎了要撒硫粉 温度计接触热水,水银为何先下降后上升 高中有机化学里各个需要温度计的实验中温度计水银球的位置分别在哪里还有没有?还有没有啊? 硫粉是什么,对吸收水银有用吗?因为偶家温度计破了,听别人说硫粉可以吸收水银. 当将水银温度计放入热水中时,会看见水银柱先是下降再上升,为什么? 有一种测量空气湿度的温度计 所示 它是由两支相同的温度计组成的 其中一只温度计正处于空气中另一只温度计乙的玻璃泡浸在潮湿的海绵中 将其放在室内 其中 的示数小 这是因为 .两示数 温度计中的水银如果误食几粒有什么后果我家温度计04年买的,那天不小心弄碎了,掉出了大约10几粒,请问误食掉几粒有什么后果? 救救我吧,中午打碎了一般水银温度计,晚上打破了电子温度计,当时我宝宝也在她刚42天,我该怎么办啊急.谢谢了我还没有分. 用温度计插入热水中测量热水的温度时,为什么开始时水银柱略微下降,然后在上升?分析是什么原因?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn