Skip to content

对象解构

对象解构的基本使用

对象解构就是使用与对象匹配的结构来实现对象属性赋值。使用解构,可以在一个类似对象字面量的解构中,声明多个变量,同时执行多个赋值操作:

js
// 使用对象解构
let person = {
  name: 'Matt',
  age: 27,
}
let { name: personName, age: personAge } = person
console.log(personName) // Matt
console.log(personAge) // 27

如果想让变量直接使用属性的名称,那么可以使用简写语法:

js
let person = {
  name: 'Matt',
  age: 27,
}

let { name, age } = person
console.log(name) // Matt
console.log(age) // 27

如果引用的属性不存在,则该变量的值就是 undefined

js
let person = {
  name: 'Matt',
  age: 27,
}
let { name, job } = person
console.log(name) // Matt
console.log(job) // undefined

在解构赋值的同时还能定义默认值,适用于引用的属性不存在的情况:

js
let person = {
  name: 'Matt',
  age: 27,
}

let { name, job = 'Software Engineer' } = person
console.log(name) // Matt
console.log(job) // Software Engineer

解构在内部使用函数 ToObject() 把原数据解构转换成对象。这意味着对象解构的上下文中,原始值会被当成对象,同时也意味着 nullundefined 不能被解构,否则会抛出错误:

js
let { length } = 'hello'
console.log(length) // 5

let { constructor: c } = 4
console.log(c === Number) // true

let { _ } = null // TypeError
let { _ } = undefined // TypeError

解构并不要求变量必须在结构表达式中声明。如果是给事先声明的变量赋值,则赋值表达式必须包含在一对括号中:

js
let personName, personAge
let person = {
  name: 'Matt',
  age: 27,
}

;({ name: personName, age: personAge } = person)
console.log(personName) // Matt
console.log(personAge) // 27

嵌套解构

解构赋值可以使用嵌套解构,以匹配嵌套的属性:

js
let person = {
  name: 'Matt',
  age: 27,
  job: {
    title: 'Software engineer',
  },
}
// 声明title变量并将person.job.title的值赋给它
let {
  job: { title },
} = person
console.log(title) // Software engineer

在外层属性没有定义的情况下不能使用嵌套解构:

js
let person = {
  job: {
    title: 'Software engineer',
  },
}
let personCopy = {}

// foo在源对象上是undefined
;({
  foo: { bar: personCopy.bar },
} = person)
// TypeError: Cannot destructure property 'bar' of 'undefined' or 'null'.

// job在目标对象上是undefined
;({
  job: { title: personCopy.job.title },
} = person)
// TypeError: Cannot set property 'title' of undefined

部分解构

如果一个解构表达式涉及多个赋值,开始的赋值成功而后面的赋值出错,则整个解构赋值只会完成一部分:

js
let person = {
  name: 'Matt',
  age: 27,
}
let personName, personBar, personAge
try {
  // person.foo是undefined,因此会抛出错误
  ;({
    name: personName,
    foo: { bar: personBar },
    age: personAge,
  } = person)
} catch (e) {}
console.log(personName, personBar, personAge)
// Matt, undefined, undefined

函数参数解构赋值

在函数参数列表中也可以进行解构赋值:

js
let person = {
  name: 'Matt',
  age: 27,
}
function printPerson(foo, { name, age }, bar) {
  console.log(name, age)
}
function printPerson2(foo, { name: personName, age: personAge }, bar) {
  console.log(personName, personAge)
}
printPerson('1st', person, '2nd')
// ['1st', { name: 'Matt', age: 27 }, '2nd']
// 'Matt', 27
printPerson2('1st', person, '2nd')
// ['1st', { name: 'Matt', age: 27 }, '2nd']
// 'Matt', 27