ES6解构掌握的怎么样?进来测试下!

54 阅读4分钟

什么是解构?ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。下面有8道解构使用的案例,来测试下自己的掌握程度,我会把案例和答案分来,方便先自己尝试回答输出结果。

案例

1 解构别名

let obj = {a: 1, b: 2}
let {a: b} = obj
console.log(b)

2 嵌套对象解构

let obj2 = {
  a: 'hello',
  b: [
    'world',
    {c: "!"}
  ]
}
let {b: [{c}]} = obj2
console.log(c)

3 数组解构

let [a, b, ...c] = [1]
console.log(a,b,c)

4 解构默认值

const fn = () => {
  return 2 
}
let [a = 1, b = fn(), c = 4] = [1, 3]
console.log(a, b, c)

5 解构的有效赋值

let [a, b = a, c = a, d = a] = [1, undefined, null, '']
console.log(a, b, c, d)

6 解构方法

let {toString: s} = 123
console.log(s === "123")

7 函数参数解构

console.log([[1, 2], [3, 4]].map(([a, b]) => a + b))

8 ?

let [a, b, c] = {a: 1, b: 2, c: 3}
console.log(a, b, c)

答案及解析

1 解构别名

let obj = {a: 1, b: 2}
let {a: b} = obj
console.log(b)

答案:1

说明:这句解构表示,要解构出来变量a,并且取别名叫b,不要被对象中的b变量干扰。

2 嵌套对象解构

let obj = {
  a: 'hello',
  b: [
    'world',
    {c: "!"}
  ]
}
let {b: [{c}]} = obj
console.log(c)

答案:undefined

说明:这段解构对象比较深层,我们需要解构的变量是c,所以我们排除掉其它干扰,剩下的解构就类似:let [{c}] = ['world',{c: "!"}],需要注意数组的解构是基于迭代器的,也就是说我们需要解构的变量和数组的值是一对一对应的,所以[{c}]就表示从数组的第一项的对象中解构出来变量c,但是第一项是字符串,所以得到的结果就算undefined

3 数组解构

let [a, b, ...c] = [1]
console.log(a,b,c)

答案:1 undefined []

说明:解构顺序从左向右,如果解构不成功,变量的值等于undefined,所以b是undefined,c变量将剩余的值收集到数组中,由于数组中只有一个值并且赋值给了a变量,所有c为[]

实际开发从数组中解构的使用相对从对象中解构使用的少点,所以同理可以试下这个解构会输出什么?

let {a, b, ...c} = {a: 1, b: 2, c: 3, d: 4},输出a,b,c结果是1 2 { c: 3, d: 4 }

4 解构默认值

const fn = () => {
  return 2	
}
let [a = 1, b = fn(), c = 4] = [1, 3]
console.log(a, b, c)

答案:1 3 4

说明:解构是可以赋默认值兜底的,前提是解构失败的情况下,上面的代码a和b都能解构成功,所以默认值就不会生效,c解构失败所以使用默认值。

5 解构的有效赋值

let [a, b = a, c = a, d = a] = [1, undefined, null, '']
console.log(a, b, c, d)

答案: 1 1 null ''

说明:解构的过程,ES6内部使用 === 去判断一个位置是否等于undefined,只有严格相等,默认值才会生效。所以上面的解构代码会拿数组的每项和undefined做全等对比,只有b满足,所以b取默认值。

6 解构方法

let {toString: s} = 123
console.log(s === "123")

答案:false

说明:解构赋值时,如果等号右边是数值和布尔值,则会先转为对象,相当于(let {toString: s} = Number.prototype)。解构出来的toString只是方法并不会执行,所以s === Number.prototype.toString才会返回true

7 函数参数解构

console.log([[1, 2], [3, 4]].map(([a, b]) => a + b))

答案:[ 3, 7 ]

说明:不看map的话,我们可以把函数看成是这样的([a,b]) => a+b,表面上这个函数接收的是一个数组,但在传入参数的那一刻,数组参数就被解构成变量ab

8 ?

let [a, b, c] = {a: 1, b: 2, c: 3}
console.log(a, b, c)

答案:你会获得一个报错,TypeError:xxx is not iterable

说明:这个报错的意思是说后面这个对象是不可迭代的,原因是数组的解构是基于迭代器的(对象的解构是基于属性的枚举和复制),在js中普通的Object对象是不可迭代的,所以会报错。

如果想要这个解构不报错,我们需要为这个对象添加一个迭代器函数:

let obj = {a: 1, b: 2, c: 3}
obj[Symbol.iterator] = function () {
  let index = 0

  function next () {
    return {done: index >= Object.keys(obj).length, value: obj[Object.keys(obj)[index++]]}
  }

  return {next}
}
let [a,b,c] = obj
console.log(a,b,c) // 1 2 3