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

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

时势造英雄:中国早期O2O创业故事 iOS开发与Android开发的四大不同 “消极抵抗”AWS OpsWork?RightScale首次宣布转售并支持GCE 2012年VC都把钱投给了哪些大数据初创公司? 耐用性将成苹果iWatch最大挑战 Sphinx:首款全硬件加速HTML5游戏引擎发布 PayPal创始人Levchin又创办了一家移动支付公司Affirm Zuck、Bill Gates、Jack Dorsey上银幕激励孩子编程 十款最新开源的开发者工具/应用(组图) Django 1.5发布,Python 3开始进入主流? [爆料]英特尔:将Hadoop“固化”到Xeon中 姗姗来迟:微软终于发布Windows 7 IE10正式版 谷歌推Google+登录系统 与Facebook争夺用户信息 微软在CodePlex上开源C++ REST SDK 代号Casablanca 论OpenAPI的起源与历史 LinkedIn开源低延时变化数据捕获系统Databus 微软发布全新WP应用 随时查看App崩溃信息 做iOS开发,我为什么弃用Objective-C而选择RubyMotion? Stinger Initiative:让Hive提速100倍 2013年云计算的九大威胁 W3C小组发起新“汽车与Web平台业务组”项目 苹果CEO:请忘掉股价 未来依然有伟大产品 两周营收100万,GO桌面在Google Play做对了什么 “吸金王”Puzzle & Dragons是如何炼成的 初创公司Kickboard:让父母了解孩子的在校表现 Rackspace收购开源数据库公司ObjectRocket 投资人表示微软应推出iPad版Office 三星:谷歌养大的一匹狼 UC九游年度战略:2013计划分成超3亿元 X-Canvas:UC将发布高性能HTML5游戏引擎 淘宝:OceanBase分布式系统负载均衡案例分享 300分求多线程解决哲学家进餐问题的源码 关于datalist 武汉的朋友帮忙啊! 严打! 我是新手,谁能告诉我如何新建类? 各位GGJJ,帮帮忙!如果每点击一次button建立一个线程,建立多个不同的线程,怎样实现? 请问那位windows98高手可以帮帮忙忙 各位GGJJ,帮帮忙!如果每点击一次button建立一个线程,建立多个不同的线程,怎样实现? 关于XML中NODE的类型的问题(特急!!!) 大家来帮小弟以下啊,!!! 如果我把一个TAdoQuery变量送到子函数中? 谁能告诉我Bjarne Stroustrup应该怎么读? 说了半天到底谁的是正确的?在100分。delete p 是删去p指针,还是它指到的内容,*p。还是删去什么?free(p) 呢? 大家好,我有一个问题问一下你们很急的。我在线等待!!! 我要去上海找工作(java) 在线提问:各位朋友帮忙啊!很急啊! 关于通过telnet修改2000的用户密码问题 请问有无现存的四舍五入函数?(in vc) 请指教有关bde和9i的问题 帮助!谢谢! 着急!!!!!!!!!!!!!!! 关于CHM文件的菜鸟问题 各位帮帮忙,我的程序重要用定时器,怎么做呀? 为什么没法看贴子? 如何在PB8。0上创建可执行文件,,,,,,(请详细一点) 关于TStrings怎样去取值? 如何编程更改IP? 谁来帮帮我!!!!! 生成密码字典,有什么好主意呢?说说好么? 有关c++中何时分配内存的问题 急救!! 请教:有关列表框 谁有win98操作培训讲义,给我发一份到—— win2000下如何对并口进行操作? 请教IBM Open Class Libraries的问题 小弟高分求“Linux 0.02版”的源代码! 理解csdn,以后再不发政治问题的贴了。我的名字也马上改。 什么是流???(笑话) 讨论.net平台上的软件开发,请教高手 书和方法! 斑竹不要删这个帖子,别人给我做了一个FLASH网站,我放50分给他的:) 为什么看不到 关于拷贝函数 最老的帖子是什么呀?第一张帖子是谁发的呀? 我想使上下结构的网页框架位置不可以调(上方的导航条固定). WebLogic过期了,在线等待! 高手手请进!文本文件数据库表的问题?????? NOTES中如何实现这样的语句? 老板拿枪指着我,关于开共享,十万火急!! treeview控件中节点上鼠标右键点击的事件如何处理,急?!! WORD中使用VBA的一个问题 请问真空高压断路器的电路图那有?或者里面机构的运动分析. 半径为R的半球形碗内表面光滑,一质量为M的小球以角速度ω在碗内一水平面做匀速圆周运动,则该平面离碗底 欧洲人均GDP的增长率下降的原因 电流在某断电路所做的功与什么有关 尖峰电流,短路电流在选择元件时主要区别? 一道初三的物理计算题.如今大城市普遍存在着停车难的问题.如图是“路边空中绿化存车亭”的工作原理图,存车时只需40S就可以把车子从地面升起停在2m的高空.其中A为存车架,O为杆OB的转动 电路短接后好像会截掉电流.怎么回事啊?整天碰到这些题就头疼. 电流互感器短路时最大整定电流可以达额定电流的几倍 什么是交流电、直流电、电阻、怎么使用万用表?怎么知道这个输出是交流电、还是直流电?电阻是什么? 五个长,宽,高分别是5厘米,5厘米,1厘米的长方体叠成一个正方体,这个正方体的体积是( ).急用 短路器的额定电流如何调节 单P的断路器 如何接线,连接开关、电灯~蓝线走哪里?如图单P的断路器 如何接线,连接开关、电灯~蓝线走哪里?如图 1p+N漏电断路器零线火线接反了会出现什么现象 王叔叔汽车的油箱有22升油他要去距家240km办事按每升汽油可行驶6.4千米计算,油箱汽油够不够? 这开关怎么才能 各自 控制一个电灯,互不影响、求接线图.我想让这上面的俩开关各自控制一个电灯 互不影响,应该怎么接线,第3个孔里是空的, 三根火线接在4P漏电保护器上端,一根零线接在漏电保护器的下端时漏保怎么老跳 2011年人均GDP增长率是多少啊? 钢绳最多承受6000n的拉力,在不计滑轮·吊钩·绳的自重及摩擦时一次最多能吊多少n 家庭电路中,当进户线的火线与零线的电路不相等,且差值达到一定值时,安装在干路上的漏电保护器就会切断电路,则下列情况可能使漏电保护器切断电路的是A、用电器短路B、用电器金属外壳 双控开关的电路在实际接线中是怎样接的呢?我能够看懂双控开关的电路图,可是实际电路中,我们的三根线(火线,零线,地线)又是怎样接入开关上的呢,另外,我很想知道双控开关上有几根接线头, 长l的绳子一端系一质量为m的小球,另一端为圆心,使小球在光滑水平面内做匀速圆周运动.当角速度为w时,绳子就要断裂.若用同样长的这些两股绳子系住小球m,使它仍在此水平面内做迅速圆周运 体积是1dm3密度是4X10三次kg/m3的实心合金球投入足够多的水槽体积是1dm^3,密度是4×10^3kg/m^3的实心合金球,投入足够多的水槽中沉底后静止.(2)将它与一块体积是8dm^3的木块连在一起后再入水槽 如图所示,质量为m的小球与穿过光滑水平板中央小孔O的轻.一质量为m的小球与穿过光滑水平般中央小孔O的轻绳相连,用手拉着小球的另一端使小球在水平板上绕O做半径为a、角速度为w1的匀速 定长的绳子的一端系一质量为m的小球,以一端为圆心,使小球在光滑水平面内做匀速圆周运动.当速度为V时,绳子就要断裂.若用同样长的这样两股绳子系住小球,使它仍在此水平面内作匀速圆周 1.体积是1dm3,密度是4×103kg/m3的实心合金球,投入足够多的水槽中沉底后静止.(1)球对槽底的压力是多大 有一光滑水平板,板的中央有一小孔,孔内穿入一根光滑轻线,轻线的上端系一质量为M的小球,轻线的下端系着质量分别为m1和m2的两个物体,当小球在光滑水平板上沿半径为R的轨道做匀速圆周运 磁体能否靠近录音带,为什么? 如图所示,在水平固定的光滑平面板上,有一质点为m的质点p,与穿过中央小孔的绳子H的轻绳一端连着.平板与小孔是光滑的,使质点做半径为a,角速度为w1的匀速圆周运动.若绳子迅速放松至某一长 一根长72厘米的铁丝,折成一个长,宽,高的比是3:2:1的长方体模型,这个模型的体积是 立方厘米.急用! 据说录像带和录音带都不能靠近磁体,把永磁体靠近录音磁带,你认为会产生什么后果,请说出你的道理 两个体积相等的正方体叠成一个长方体,长方体的高是12厘米,这个长方体的体积是多少立方厘米 利用公式 空气开关跳闸说明电路中出现短路,请问这个问题是对还是错 居民人均可支配收入增长率指什么? 额定短路分断能力过小会有什么后果 有一根铁丝长144米,制成一个长方体,长、宽、高的比是3:1:2,这个长方体的体积是多少立方米? 2010年中国人均可支配收入是多少?人均GDP是否已达3000美元? 一个长方体的高是2厘米,再叠一个同样大小的长方体,就可以成为一个正方体,原来长方体的体积是多少立方厘米 把一根2米长的铁丝折成一个长15厘米,宽10厘米的长方体,这个长方体高()厘米.这个长方体的体积是() 人均GDP 和人均可支配收入有什么区别 .额定短路和分断能力Icu=lcs:6000A;是什么意思 用一根长192厘米的铁丝,围成一个长,宽,高的比是3:2:1的长方体,求围成的长方体体积是多少 如果说悬绳的拉力等于重力,物块对地面的压力 等于重力,这种说法对吗 26、 如图所示,容器底部用一根细绳挂住一木球,使木球完全浸没在水中,已知木球的密度是水的密度的3/5,如图所示,容器底部用一根细绳挂住一木球,使木球完全浸没在水中,已知木球的密度是水 湖北省市级城市的人口数量和人均GDP 在电视机旁使用电吹风时,会看到电视画面闪烁;彩色电视机说明书上标明忌与磁体靠近.这是为什么? 一松木球悬浮于油和水的分界面处,且木球浸入油和水的体积比是3比1.那么油的密度是多少?木的密度是0.4X10^3Kg/m^3 如果GDP增长率是7%,人口增长率是1%,那么人均GDP增长率是多少? 充电器输出电流不够对电池有影响么家里有个zune播放器,充电器是5v1.5a的,可是市场能买到5v1a的,对于播放器电池有什么影响? 两个实心木球的半径之比为1:2则它们的密度之比为什么?体积之比为什么?质量之比为什么? 进水车怎么修 为什么彩色电视机说明书上标明勿与磁体靠近 装修完漏电开关总掉,零线、火线、地线都对调过,没用,我家刚装修完,厨房电路总是漏电开关跳闸,我把零线、火线对调了,可过1个月后又掉闸,从此漏电开关推上去5分钟后就自己掉,所有电器我 汽车发动机进水车有什么反应 为什么我们常见到的CRT彩色电视机说明书上标明“勿与磁体靠近”? 实心木球的密度是0.4×10⒊kg/个金属图我没办法画了 实心木球的密度是0.4×10⒊kg/m⒊,木球下面用细线及一个金属球,木球的体积是金属块的2倍,把他们放入水中恰好悬浮,球金属块的密度 沿半径为R的半球形碗底的光滑内表面,质量为m的小球以角速度w在一水平面内做匀速圆周运动,试求此时小球离 甲乙两个小镇长75千米.西西驾驶一辆汽车行驶30千米用去2升汽油.照这样计算行完全程还需几升汽油 提问一道物理计算题 机车以3.2×10的五次方N的推力推动火车在轨道上缓慢匀速滑动了50m后脱离了危险地带.若火车总重为1.5×10的七次方N,铺设轨道的地面能承受的最大压强为7.5×10的五次方Pa. 泡水车是什么意思 gdp总量人均gdp gdp增长率反映着什么
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘