ES6中的解构
要储存和设置数据,我们一般采用最多的是单个变量,而对于多个数据、复杂类型的处理,我们则会使用数组或者对象。它们组成了目前最为流行的数据格式 - JSON。而为了更加方便的定义和处理数据,ES6 中引入了 解构(destructuring) 的概念。
解构的操作主要体现在赋值方面,它可以从数组或者对象中提取数据赋值给不同的变量。解构赋值有对象解构赋值、数组解构赋值。接下来,看看它都有哪些内容。
一、对象解构赋值
1.1 同名解构赋值
我们在获取一个对象后,需要提取对象里的属性进行操作,但为了使源对象保持不变,通常我们会用一些变量保存对象里的属性,然后再进行相关操作:
var person = { |
试想下,如果需要提取对象里的多个变量,那就需要逐个一一声明、赋值,这显然很繁琐,并且增加很多重复的代码。
针对上面的问题,ES6 引入了 对象解构赋值。可以同时声明多个变量,并且赋值,这极大的方便了数据的操作:
var person = { |
其实上面的代码 {name, age} = person
相当于 {name, age} = {name: 'yix', age: 28}
。 {name, age} = person
这个赋值表达式的左边是定义的变量,变量名与对象属性名必须相同,且一一对应。如果对象中找不到对应变量名的属性,则该变量会返回 undefined
。
如果你要同时改变多个已经声明赋值过的变量的值,你也可以通过以下方式:
var person = { |
或许你已经注意到上面的解构代码被一个小括号括了起来,这是因为如果不用小括号的话,{name, age}
会被当成代码块处理,而这样会引发错误。
1.2 默认参数
在写插件时,为了避免用户不设定参数的情况,通常会指定若干个默认参数。而通过上面的例子我们也知道,如果声明的变量未在对象中找到,则会返回 undefined
。这当然不是我们希望的,幸好,ES6 允许我们给变量指定默认值,方式如下:
var person = { |
1.3 异名解构赋值
这里的 异名解构赋值
是相对于上面的 同名解构赋值
而言,前面说了,解构赋值中左边的变量名必须和右边的对象属性名相同,否则无法正常获取对应的属性值。但倘若你就是不想使用同名变量,ES6 也可以满足你,只需要像下面这样:
var person = { |
上面解构代码声明了 myName
和 myAge
这两个变量,而其中的 name
和 age
会读取 person
对象的属性,并把属性值赋值给声明的这两个变量。注意,这里是左边为 “属性值”,右边为 “属性名”,赋值是从左边到右边,而普通对象却是相反,左边属性名,右边则是属性值。
当然,你也可以在 异名解构赋值
中设置默认值:
var person = { |
1.4 嵌套解构
对于一些复杂的对象,我们要获取嵌套在内部很深的属性,通常需要类似 obj.property.propertySon1.propertySon1Son
这样的形式。而使用解构,则能快速获取想要的值,如:
var person = { |
同样地,你也可以在 嵌套解构
中设置 异名解构赋值
,只是,看起来会有些混乱:
var person = { |
二、数组解构赋值
2.1 解构赋值
相比与对象是根据属性来解构,数组则是根据数组项(项位置)来解构。通常而言,我们需要分别写多行来定义一个变量,比如:
var name = 'yix', |
但是,如果你通过数组解构的方式来声明赋值,则可以同时声明多个变量:
var info = ['yix', 28, ['xx@126.com', 'xx@163.com']]; |
从上面的代码可以知道,左边变量定义的顺序和右边数组 info
中的数组项一一对应,并且变量的值也是对应数组项的值。我们可以尝试着调换变量顺序:
var info = ['yix', 28]; |
由上面的例子,变量顺序调换,数组(值)不变,则第一个变量仍然是对应数组第一项,这也说明了数组的解构是取决于数组项的顺序。而对于没有对应数组项的变量,它的值就是 undefined
,这与 ES5 是相同的,即 只声明、不赋值。
基于是按照顺序来解构这一规则,我们就能请轻松的交换两个变量的值:
var a = 1, |
如果是在 ES5 时期,我们必须借助第三个变量才能完成这项工作。
或许,你会觉得这个数组解构没有对象解构方便,因为它要一一对应,这和函数中传入多个参数一样,你要判断参数的位置,采取容错措施,而如果你传入的参数是一个对象,你只需要判断对象的属性即可。
其实这点你大可不必在意,因为数组解构的变量定义中,你可以省略一些变量名称,直接取你需要数组项的值,比如,在下面的代码中,我只需要获取 email
信息,那么我可以通过省略其中的项,只定义我需要的数组项的变量:
var info = ['yix', 28, ['xx@126.com', 'xx@163.com']]; |
如果你要同时改变多个已经声明赋值过的变量的值,你可以通过以下方式:
var info = ['yix', 28]; |
需要注意的是,如果解构的右边不是数组,则会出现语法报错。
2.2 默认参数
和对象类似,数组解构中也有默认参数,对于没有对应项数组值的变量来说,而已是再合适不过:
var info = ['yix']; |
2.3 嵌套解构 和 Rest 参数
目前为止,我们只看到简单的对应关系。但实际编码过程,可能会存在一些复杂的嵌套解构,但基本原则是不变的:
var info = ['yix', ['xx@126.com', 'xx@163.com'], 28]; |
假设定义的变量中存在 Rest 参数,如果 Rest 参数变量有对应的项,则 Rest 参数的值为 剩余数组项所组成的数组。如果没有,则 Rest 参数的值为一个 空数组,来看代码:
// 有对应项 |
三、解构特殊值
在前面,我们对对象、数组进行解构。但需要注意的是,并不是什么值都能解构,我们尝试着把解构的值的数据类型依次设置为 数字、NaN、字符串、null、undefined,看看会得到怎样的结果:
当解构的值为 数字 时,会抛出一个错误:
var info = 1; |
当解构的值为 NaN 时,会抛出一个错误:
var info = NaN; |
当解构的值为 字符串时,会将字符串先分解(split)成数组:
var info = 'ab'; |
当解构的值为 null时,也会抛出一个错误:
var info = null; |
当解构的值为 undefined 时,同样抛出一个错误:
var info = undefined; |
四、应用
4.1 复杂的数据提取
前面也说过,对于一些复杂的对象,我们要获取嵌套在内部很深的属性,无论提取的值是数组还是对象,通常需要类似 obj.property.propertySon1.propertySon1Son 这类操作。
但如果你用解构,则能轻松的提取想要的信息:
var info = { |
上面的代码的目的是提取 info 对象中联系方式的 第一个邮箱,以及 晚上活动的时间 。
4.2 函数参数设置
我们经常会对函数做一些预留参数,如果用户不设置这个参数值,则在程序运行时,该参数会使用我们设定的默认值,而通常的做法,就是使用 或
的方式,如下面的一个简单的 ajax方法 :
function ajax(url, opt) { |
我们会对参数对象中的一个或者多个属性设置一个默认值,每个都要设置一遍,这样显得特别繁琐。还记得前面讲到的对象中的默认参数吗?我们可以用它来改下上面的形式,这样一来,代码就变得十分简洁了:
function ajax(url, { |