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

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

一个小巧精致的CPU监视器 -VB资料 应用VB4.0实现工业控制的实时曲线和历史曲线 应用程序中实现关机功能-VB资料 萤幕抓取与萤幕保护程式 -VB资料 用VB5.0创建Windows快捷方式 用VB5.0收集键盘和鼠标信息 用VBA限制非注册软件使用时间 用VB编程检测当前电池使用情况 用VB编写定时关闭计算机的程序 用VB编写键盘拦截程序 用VB函数轻松访问系统注册表 用VB设计一个定时闹钟程序 用VB实现拖放功能 在VB中启动控制面板 在VB中异步执行程序 在Visual Basic中终止Windows 95 在关机或Logff前信息的拦截-VB资料 VB怎样捕捉窗体的鼠标? VB怎样存取注册表信息 VB怎样改变双击鼠标的时间间隔? VB怎样关闭一个正在运行的程序 VB怎样限制鼠标移动 ANI文件格式 -VB资料 AVI文件格式-VB资料 DBF文件转为MDB文件的方法 -VB资料 FLIC动画文件的播放程序设计-VB资料 MS Office 开发工具VBA TextBox 中英文输入方法切换-VB资料 TXT文件的读取-VB资料 VB 如何将dbgrid印出来 VB5.0调用Office97技巧 请问有关group by,并且insert数据的问题. 如何设置edit中的内容自动折行,能出现垂直滚动条???在线等待!!! 关于在DLL中使用Mscom控件的问题 如何將字符串以十六進制的形式顯示在Edit中 关于SOCK5代理服务器的第二次协商问题? 为什么oracle的sql语句的表名必须加“”??? 谁能解决工具条中的一问题?50分相送 ##### 100分求教:如何实现框架集下页面的定向输出?##### 菜单菜单!!! 如何用Schema验证XML文档 JSP中jsp文件和bean的class文件的相对位置是怎么样啊? excel中的两个问题:1、如何关闭userForm1窗口?2、如何在打开userForm1窗口时使主窗口最小化? Dll函数问题 咋判断用户点的四点能围成一个四边形? 网站中的某一页嵌入VB的AtiveX 控件,客户端能访问网站,但不能打开AtiveX控件。。。高分 请问怎么把 string 型转换成 System.Data.SqlDbType 型? 机器无法启动 主板有问题吗 高分请教 创建不了C#Web项目,急!!!(刚学C#) [求助] 用fopen函数读不出URL文件? 怎么判断listview是否有一个item被选中? 请说一下硬盘容量和内存容量的关系! ▄▅▆▇█ 水园的大背景离不开吵架 █▇▆▅▄ 请教mm有个问题! linux下的编程问题 以Oracle为例说明如何通过ODBC将数据库中的指定表导出到MDB数据库。(原创) 关于一种特殊按钮 SQL语句小问题!!在线等待! 想学ColdFusion 请看我的转载的贴子 Troj_Hacline.A是什么病毒? 关于XML的问题,150分赠送,急 dll问题。很简单。 感慨!!!(潜水一年,吐个泡,顺便发表一点意见) 帮个忙 怎么在Installshield中创建对话框,并操作ACCESS数据库? 连续给分:邮件服务器防病毒问题! 我想编译一个像API一样的dll 启动rose就出错,高手来看,100分 关于打印的一个问题 急!!!请提供一段设置Session的全部代码,谢谢!! 请问,从第二帧开始播放的代码的什么??? 老师要求编写五子棋的程序可是我实在想不出该怎么设定估价函数啊帮帮忙啊? 感觉压力比较大,活不下去,想跳楼自杀的进来侃侃 一个关于php提交表单的问题。 各位大侠,要命问题! 怎么在Installshield中创建对话框,并操作ACCESS数据库? win2000server的管理员密码让人改了,怎么办呀! 太气愤了,帮帮我? 用BDE连接MS SQL SERVER,为什么运行后出现未知用户名或密码的错误? datagrid中能不能进行统计 如何编写“outlook”风格的界面 遗憾的近义词和反义词 膀胱欠充盈是什么意思 热力学上的二级相变是什么? 日本明明是君主立宪制,为什么明治维新改革后还设立了专门效忠天皇的“皇军”,保留了皇权?如果明治维新改革后没有君主立宪,那日本关于君主立宪的改革是在好久?不过我真的好像只知道 We have an English class___9:30___Friday.急……谢谢哈. 陨石 爆炸会引发黑洞不? 与日本明治维新后的君主立宪制相似的国家是 when do you have English?答句可以是We have English at 10:00 on Friday. 宇宙里,被卷入黑洞后,会去哪里?我觉得不应该消失的无影无踪,因为你可以自己想想,一个物体不会忽然没有这个物质了吧?我觉得被卷入黑洞后,是不是带物体去了另外一个空间?(不是宇宙里 西方国家所称的“毕达哥拉定理”在中国则被称作? 可以用吸管做什么科学小实验?想在物理课上做一些小实验- 3Q 我国武装力量是由哪几部分组成的?分别说明,具体点, 人的膀胱容量多大啊 怎样用吸管搭出能承受一定重量的桥?材料为25根吸管,20根牙签,以及103型粘性标签纸,不能使用其他材料.求详细的设计说明,最好有图. 果园今年收苹果450千克,收的梨比苹果的4倍少168千克,果园今年收梨多少千克? 人类膀胱容量的极限是多少?如题 6跟吸管搭桥6根吸管搭桥吸管直径5mm,长19cm还有线绳1.6m怎么搭出最结实的桥?蓝色的是原封不动的吸管绿色的是剪过之后的吸管黑色的是固定三根长吸管的线红色的点是用线固定的点这是我设 人非生而知之者 孰能无惑的而 我对象对我很好,可是又有人追我,我该怎嘛办 沉重的反义词是 2012光子带 什么样子的人会死去 子弹射在墙上会不会反弹啊 沉重的反义词时是什么 2012进入光子带时会怎样,要全一点的,进入之后呢?什么人会死 人非生而知之者 孰能无惑相同意思的格言要大于3句 沉重的反义词是什么? 急! 2012会进入光子带吗?我们会死吗?我才14岁啊 不要复制 看多了我艹 真死假死 不能开玩笑的! 人非生而知之者 孰能无惑是什么名言 沉重-( )[反义词] 想自己在家里用电灯泡孵化小鸡,我找到个资料,不到能不能孵,有经验的人提提意见.准备个箱子要孵多一些箱子就大些,在底下垫棉花,把鸡蛋放在上面,拿一个60瓦的灯泡,放在比鸡蛋高一寸的地 膀胱充盈欠佳,B超结果我妈妈更年期了. 如果南极的企鹅养在我们居住的地方,要注意什么问题?要 注意的是温度. 人非生而知之者,孰能无惑告诉我们一个什么道理 膀胱充盈差的意思是什么我经常憋尿有时五六个小时,甚至是七八个小时才上厕所,后来感觉憋久了就不胀了,还有憋久了感觉好像是胸口都胀了,我担心有问题,我就去医院做了尿检和膀胱的检 MT是什么意思 用19这个数字和创造结合起来设计一个标志, 膀胱充盈欠佳是什么意思? Western杂交就是western blot 莫, 如图,直线CD,EF相交于点O,OA⊥OB,OF平分∠AOD,∠BOE=2∠BOC,求∠BOC的度数如题 膀胱不充盈是什么意思去医院做B超.他说我膀胱不充盈.医生没说什么.当时我是流产了.和这有关系吗 Western杂交中,为何要引入二抗?为何不在一抗上直接加上放射性同位素或者GFP? 含反义词的成语写出五个 霉(梅)西是发霉的西瓜吗? western杂交可否用于检测酵母菌基因组特征 谁能打出下面这个符号 急用 西瓜豆酱,豆糁的制作河南开封做的西瓜豆酱,和干豆糁是怎么制作的.西瓜豆酱和豆糁是两种做法,请高手制作方法 没有一个说的详细的,都是在网上收下来的, 要是住在南极的企鹅生活在热带会怎么样 人非生而知之者 孰能无惑的意思 豆酱发好了霉却没太阳晒如何办 南极的企鹅可以在北极生活吗? 怎样防止小鸟吃田地里的庄家 人非生而知之者,孰能无惑?《师说》的说读什么音?谁知道的? 如何去掉质谱中的杂峰? 用LCMS测试样品时质谱中总是存在143的峰,更换流动相后仍有此问题,请问如何解决 诱使1998年嫩江和松花江大洪涝灾害的根本原因是什么 人非生而知之者,孰能无惑?的意思!急 为什么热力学基本关系式不适用与相变? 人非生而知之者,孰能无惑.快 有机复合材料是混合物吗有机复合材料、无机非金属材料事混合物,还是有(无)机物 人非生而知之者,孰能无惑?的意思 请问为什么说热力学公式一般只适用于恒组成的均相封闭体系?比如等压反应热等于焓的改变值的公式适用条件是封闭体系等压的物理化学变化过程就可以了,那和上面的说法又不一样了…… 泰国反赦免法案集会升级 英拉流泪劝放叙利亚总理说消灭“恐怖势力”只是时间财经观察:英国经济复苏路上的政党博弈中国男子在日本偷车被捕 日警方连开4秘鲁与法国签署防务合作协议环球佳丽秀美衣 美国小姐化身“变形金强生违法销售药品 在美被罚22亿美元法国颁发龚古尔、勒诺多两大文学奖经济观察:中国经济在转方式调结构中走孙杨无证驾车拘七天罚两千 致歉信被批人民日报谈“免费医疗”:天下没有“免闯关破障——改革如何突围?网曝四川一镇长上班看《新白娘子传奇》中国疾控中心、国家流感中心:H7N9北京119指挥中心:寒衣节烧纸引火灾北京:明年购车摇号指标净减9万 暂不激活社会资本 释放市场能量——十八大法5名醉汉从马戏团\"绑架\"一只羊美国安局被曝重点监视韩国 韩当局索要美国两名移民者闯入国会山抗议被逮捕美国被曝重点监视韩国 韩要求美方做详中超十轮后 舜天终变阵 “错位之战”几代读者巴金故居分享心得医生都掂着价格开中药 经典方只怕再也手机电脑族,当心干眼症“琼瑶们”担心的是什么全职太太的“转场”节奏俄副总理称改坐轰炸机杭州表态:求取最大公约数将寻找“小资”酒店做成生意为未来“由熊转牛”奠定制度基础“学霸”也可以是“球霸”规避市场波动风险 把握投资机会微博发力自媒体成长计划比求情信更重要的是敬畏生命庆祝母亲节体育彩票开奖公告暴雨“浇”塌挡土墙18死3伤火花行情有“火花”上海市地名管理办公室公告(2014)“生命核”启动心血管系统的自我修复重塑强直性脊柱炎患者健康
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘