Skip to content

解构和展开

解构和展开

解构是一种解包数组和对象并将其分配给不同变量的方法。

解构数组

js
  const numbers = [1, 2, 3]
  let [numOne, numTwo, numThree] = numbers

  console.log(numOne, numTwo, numThree)
sh
  1 2 3
js
  const names = ['Asabeneh', 'Brook', 'David', 'John']
  let [firstPerson, secondPerson, thirdPerson, fourthPerson] = names

  console.log(firstPerson, secondPerson,thirdPerson, fourthPerson)
sh
Asabeneh Brook David John
js
  const scientificConstants = [2.72, 3.14, 9.81, 37, 100]
  let [e, pi, gravity, bodyTemp, boilingTemp] = scientificConstants

  console.log(e,pi,gravity, bodyTemp, boilingTemp)
sh
2.72 3.14 9.81 37 100
js
const fullStack = [
  ['HTML', 'CSS', 'JS', 'React'],
  ['Node', 'Express', 'MongoDB']
]
const [frontEnd, backEnd] = fullStack

console.log(frontEnd)
console.log(backEnd)
sh
["HTML", "CSS", "JS", "React"]
["Node", "Express", "MongoDB"]

如果我们想跳过数组中的某个值,我们使用额外的逗号。逗号有助于省略特定索引处的值

js
  const numbers = [1, 2, 3]
  let [numOne, , numThree] = numbers //省略了2

  console.log(numOne, numThree)
sh
1 3
js
  const names = ['Asabeneh', 'Brook', 'David', 'John']
  let [, secondPerson, , fourthPerson] = names // 省略了第一个和第三个人

  console.log(secondPerson, fourthPerson)
sh
Brook John

如果数组中该索引的值是 undefined,我们可以使用默认值:

js
const names = [undefined, 'Brook', 'David']
let [
  firstPerson = 'Asabeneh',
  secondPerson,
  thirdPerson,
  fourthPerson = 'John'
] = names

console.log(firstPerson, secondPerson, thirdPerson, fourthPerson)
sh
Asabeneh Brook David John

我们不能将变量分配给数组中的所有元素。我们可以解构前几个元素,并使用展开运算符(...)将其余元素作为数组获取。

js
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let [num1, num2, num3, ...rest] = nums

console.log(num1, num2, num3)
console.log(rest)
sh
1 2 3
[4, 5, 6, 7, 8, 9, 10]

迭代期间的解构

js
const countries = [['Finland', 'Helsinki'], ['Sweden', 'Stockholm'], ['Norway', 'Oslo']]

for (const [country, city] of countries) {
console.log(country, city)
}
sh
Finland Helsinki
Sweden Stockholm
Norway Oslo
js
const fullStack = [
  ['HTML', 'CSS', 'JS', 'React'],
  ['Node', 'Express', 'MongoDB']
]

for(const [first, second, third] of fullStack) {
console.log(first, second, third)
}
sh
HTML CSS JS
Node Express MongoDB

解构对象

当我们解构时,用于解构的变量名称应该与对象的键或属性完全相同。请看下面的示例。

js
const rectangle = {
  width: 20,
  height: 10,
  area: 200
}
let { width, height, area, perimeter } = rectangle

console.log(width, height, area, perimeter)
sh
20 10 200 undefined

解构时重命名

js
const rectangle = {
  width: 20,
  height: 10,
  area: 200
}
let { width: w, height: h, area: a, perimeter: p } = rectangle

console.log(w, h, a, p)
sh
20 10 200 undefined

如果在对象中找不到键,变量将被分配为 undefined。有时键可能不在对象中,在这种情况下,我们可以在声明期间给出默认值。请看示例。

js
const rectangle = {
  width: 20,
  height: 10,
  area: 200
}
let { width, height, area, perimeter = 60 } = rectangle

console.log(width, height, area, perimeter) //20 10 200 60
//让我们修改对象:width为30,perimeter为80
js
const rectangle = {
  width: 30,
  height: 10,
  area: 200,
  perimeter: 80
}
let { width, height, area, perimeter = 60 } = rectangle
console.log(width, height, area, perimeter) //30 10 200 80

将键解构作为函数参数。让我们创建一个接受矩形对象并返回矩形周长的函数。

不使用解构的对象参数

js
// 不使用解构
const rect = {
  width: 20,
  height: 10
}
const calculatePerimeter = rectangle => {
  return 2 * (rectangle.width + rectangle.height)
}

console.log(calculatePerimeter(rect)) // 60
//使用解构
js
//另一个示例
const person = {
  firstName: 'Asabeneh',
  lastName: 'Yetayeh',
  age: 250,
  country: 'Finland',
  job: 'Instructor and Developer',
  skills: [
    'HTML',
    'CSS',
    'JavaScript',
    'React',
    'Redux',
    'Node',
    'MongoDB',
    'Python',
    'D3.js'
  ],
  languages: ['Amharic', 'English', 'Suomi(Finnish)']
}
// 让我们创建一个函数,在不使用解构的情况下提供有关person对象的信息

const getPersonInfo = obj => {
  const skills = obj.skills
  const formattedSkills = skills.slice(0, -1).join(', ')
  const languages = obj.languages
  const formattedLanguages = languages.slice(0, -1).join(', ')

  personInfo = `${obj.firstName} ${obj.lastName} lives in ${obj.country}. He is  ${
    obj.age
  } years old. He is an ${obj.job}. He teaches ${formattedSkills} and ${
    skills[skills.length - 1]
  }. He speaks ${formattedLanguages} and a little bit of ${languages[2]}.`

  return personInfo
}

console.log(getPersonInfo(person))

使用解构的对象参数

js

const calculatePerimeter = ({ width, height }) => {
  return 2 * (width + height)
}

console.log(calculatePerimeter(rect)) // 60
js
// 让我们创建一个使用解构提供有关person对象信息的函数
const getPersonInfo = ({
  firstName,
  lastName,
  age,
  country,
  job,
  skills,
  languages
}) => {
  const formattedSkills = skills.slice(0, -1).join(', ')
  const formattedLanguages = languages.slice(0, -1).join(', ')

  personInfo = `${firstName} ${lastName} lives in ${country}. He is ${age} years old. He is an ${job}. He teaches ${formattedSkills} and ${
    skills[skills.length - 1]
  }. He speaks ${formattedLanguages} and a little bit of ${languages[2]}.`

  return personInfo
}
console.log(getPersonInfo(person))
/*
Asabeneh Yetayeh lives in Finland. He is  250 years old. He is an Instructor and Developer. He teaches HTML, CSS, JavaScript, React, Redux, Node, MongoDB, Python and D3.js. He speaks Amharic, English and a little bit of Suomi(Finnish)
*/

迭代期间解构对象

js
const todoList = [
{
  task:'Prepare JS Test',
  time:'4/1/2020 8:30',
  completed:true
},
{
  task:'Give JS Test',
  time:'4/1/2020 10:00',
  completed:false
},
{
  task:'Assess Test Result',
  time:'4/1/2020 1:00',
  completed:false
}
]

for (const {task, time, completed} of todoList){
  console.log(task, time, completed)
}
sh
Prepare JS Test 4/1/2020 8:30 true
Give JS Test 4/1/2020 10:00 false
Assess Test Result 4/1/2020 1:00 false

展开或剩余运算符

当我们解构数组时,我们使用展开运算符(...)将其余元素作为数组获取。此外,我们使用展开运算符将数组元素展开到另一个数组。

使用展开运算符获取数组的其余元素

js
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let [num1, num2, num3, ...rest] = nums

console.log(num1, num2, num3)
console.log(rest)
sh
1 2 3
[4, 5, 6, 7, 8, 9, 10]
js
const countries = [
  'Germany',
  'France',
  'Belgium',
  'Finland',
  'Sweden',
  'Norway',
  'Denmark',
  'Iceland'
]

let [gem, fra, , ...nordicCountries] = countries

console.log(gem)
console.log(fra)
console.log(nordicCountries)
sh
Germany
France
["Finland", "Sweden", "Norway", "Denmark", "Iceland"]

使用展开运算符复制数组

js
const evens = [0, 2, 4, 6, 8, 10]
const evenNumbers = [...evens]

const odds = [1, 3, 5, 7, 9]
const oddNumbers = [...odds]

const wholeNumbers = [...evens, ...odds]

console.log(evenNumbers)
console.log(oddNumbers)
console.log(wholeNumbers)
sh
[0, 2, 4, 6, 8, 10]
[1, 3, 5, 7, 9]
[0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9]
js
const frontEnd = ['HTML', 'CSS', 'JS', 'React']
const backEnd = ['Node', 'Express', 'MongoDB']
const fullStack = [...frontEnd, ...backEnd]

console.log(fullStack)
sh
["HTML", "CSS", "JS", "React", "Node", "Express", "MongoDB"]

使用展开运算符复制对象

我们可以使用展开运算符复制对象

js
const user = {
  name:'Asabeneh',
  title:'Programmer',
  country:'Finland',
  city:'Helsinki'
}

const copiedUser = {...user}
console.log(copiedUser)
sh
{name: "Asabeneh", title: "Programmer", country: "Finland", city: "Helsinki"}

复制时修改或更改对象

js
const user = {
  name:'Asabeneh',
  title:'Programmer',
  country:'Finland',
  city:'Helsinki'
}

const copiedUser = {...user, title:'instructor'}
console.log(copiedUser)
sh
{name: "Asabeneh", title: "instructor", country: "Finland", city: "Helsinki"}

箭头函数中的展开运算符

每当我们想要编写一个接受无限数量参数的箭头函数时,我们使用展开运算符。如果我们使用展开运算符作为参数,调用函数时传递的参数将变为数组。

js

const sumAllNums = (...args) => {
  console.log(args)
}

sumAllNums(1, 2, 3, 4, 5)
sh
[1, 2, 3, 4, 5]
js

const sumAllNums = (...args) => {
  let sum = 0
  for (const num of args){
    sum += num
  }
  return sum
  
}

console.log(sumAllNums(1, 2, 3, 4, 5))
sh
15

🌕 到目前为止你已经取得了很大的成就。现在,你的JavaScript水平是中高级。继续前进!你刚刚完成了第11天的挑战,在通往伟大的道路上又前进了11步。现在为你的大脑和肌肉做一些练习。

练习

练习:级别1

js
const constants = [2.72, 3.14, 9.81, 37, 100]
const countries = ['Finland', 'Estonia', 'Sweden', 'Denmark', 'Norway']
const rectangle = {
  width: 20,
  height: 10,
  area: 200,
  perimeter: 60
}
const users = [
{
  name:'Brook',
  scores:75,
  skills:['HTM', 'CSS', 'JS'],
  age:16
},
{
  name:'Alex',
  scores:80,
  skills:['HTM', 'CSS', 'JS'],
  age:18
},
{
  name:'David',
  scores:75,
  skills:['HTM', 'CSS'],
  age:22
},
{
  name:'John',
  scores:85,
  skills:['HTML'],
  age:25
},
{
  name:'Sara',
  scores:95,
  skills:['HTM', 'CSS', 'JS'],
  age: 26
},
{
  name:'Martha',
  scores:80,
  skills:['HTM', 'CSS', 'JS'],
  age:18
},
{
  name:'Thomas',
  scores:90,
  skills:['HTM', 'CSS', 'JS'],
  age:20
}
]
  1. 解构并将constants数组的元素分配给e、pi、gravity、humanBodyTemp、waterBoilingTemp。
  2. 解构并将countries数组的元素分配给fin、est、sw、den、nor
  3. 通过其属性或键解构rectangle对象。

练习:级别2

  1. 遍历users数组,使用解构获取对象的所有键
  2. 找到技能少于两个的人

练习:级别3

  1. 解构countries对象,打印所有国家的名称、首都、人口和语言
  2. 一个初级开发者将学生姓名、技能和分数结构化为数组的数组,这可能不容易阅读。在一行中将以下数组解构为name到name,skills数组到skills,scores数组到scores,JavaScript分数到jsScore,React分数到reactScore变量。
js
  const student = ['David', ['HTM', 'CSS', 'JS', 'React'], [98, 85, 90, 95]]
  console.log(name, skills, jsScore, reactScore)
sh
David (4) ["HTM", "CSS", "JS", "React"] 90 95
  1. 编写一个名为 convertArrayToObject 的函数,它可以将数组转换为结构化对象。
js
    const students = [
        ['David', ['HTM', 'CSS', 'JS', 'React'], [98, 85, 90, 95]],
        ['John', ['HTM', 'CSS', 'JS', 'React'], [85, 80, 85, 80]]
      ]

    console.log(convertArrayToObject(students))
    [
      {
        name: 'David',
        skills: ['HTM','CSS','JS','React'],
        scores: [98,85,90,95]
      },
      {
        name: 'John',
        skills: ['HTM','CSS','JS','React'],
        scores: [85, 80,85,80]
      }
    ]
  1. 将student对象复制到newStudent而不改变原始对象。在新对象中添加以下内容?
  • 将Bootstrap(级别8)添加到前端技能集
  • 将Express(级别9)添加到后端技能集
  • 将SQL(级别8)添加到数据库技能集
  • 将SQL(无级别)添加到数据科学技能集
js
    const student = {
      name: 'David',
      age: 25,
      skills: {
        frontEnd: [
          { skill: 'HTML', level: 10 },
          { skill: 'CSS', level: 8 },
          { skill: 'JS', level: 8 },
          { skill: 'React', level: 9 }
        ],
        backEnd: [
          { skill: 'Node',level: 7 },
          { skill: 'GraphQL', level: 8 },
        ],
        dataBase:[
          { skill: 'MongoDB', level: 7.5 },
        ],
        dataScience:['Python', 'R', 'D3.js']
      }
    }

复制的对象输出应该像这样:

js
    {
    name: 'David',
    age: 25,
    skills: {
      frontEnd: [
        {skill: 'HTML',level: 10},
        {skill: 'CSS',level: 8},
        {skill: 'JS',level: 8},
        {skill: 'React',level: 9},
        {skill: 'BootStrap',level: 8}
      ],
      backEnd: [
        {skill: 'Node',level: 7},
        {skill: 'GraphQL',level: 8},
        {skill: 'Express',level: 9}
      ],
      dataBase: [
        { skill: 'MongoDB',level: 7.5},
        { skill: 'SQL',level: 8}
      ],
      dataScience: ['Python','R','D3.js','SQL']
    }
  }

🎉 恭喜!🎉