Возможна ли деструкция? - PullRequest
       29

Возможна ли деструкция?

2 голосов
/ 17 февраля 2020

Я новичок в деструктуризации и мне нужна помощь в поиске лучшего решения. У меня есть довольно сложный объект, возвращающийся в ответ, и я хотел бы его почистить. Ничего не делая, это выглядит так:


const homeTeam = {

totalPlaysFor: res.data.stats.home.teamStats[0].miscellaneous.offensePlays,

totalPlaysAgainst: res.data.stats.away.teamStats[0].miscellaneous.offensePlays

}

Я знаю, что могу сделать что-то вроде:


const { offensePlays } = res.data.stats.home.teamStats[0].miscellaneous;

, но это только решит мою проблему для одного из них и оставит другой еще долго и тяжело читать.

Ответы [ 3 ]

1 голос
/ 17 февраля 2020

Можно заранее деструктурировать свойство stats, а затем создать вспомогательную функцию, которая принимает объект .home или .away и перемещается к вложенному .offensePlays:

const { stats } = res.data;
const getOffPlays = obj => obj.teamStats[0].miscellaneous.offensePlays;
const homeTeam = {
  totalPlaysFor: getOffPlays(stats.home),
  totalPlaysAgainst: getOffPlays(stats.away)
};

, не имея автономная вспомогательная функция, вы также можете создать объект, .map пропингуя массив свойств (например, [['totalPlaysFor', 'home'], ['totalPlaysAgainst', 'away']]) и передав его в Object.fromEntries, но это будет значительно менее читабельным IMO.

0 голосов
/ 17 февраля 2020

Хотя вы можете деструктурировать это напрямую, через что-то вроде

const {
  data: {
    stats: {
      home: {
        teamStats: [{
          miscellaneous: {
            offensePlays: totalPlaysFor
          }
        }]
      },
      away: {
        teamStats: [{
          miscellaneous: {
            offensePlays: totalPlaysAgainst
          }
        }]
      }
    }
  }
} = res

const homeTeam = {totalPlaysFor, totalPlaysAgainst}

, которое выглядит довольно уродливо.

Независимо от того, думаете ли вы, что ваш код некрасив, я вижу гораздо более важную проблему с ним: он не работает, когда ни одно из этих свойств не существует. Чтобы решить эту проблему, вам может потребоваться функция, еще не вездесущая в языке, например, Необязательная цепочка , которая позволит избежать выдачи ошибок для вложенного пути, такого как 'data?.stats?.home?.teamStats?.0?.miscellaneous?.offensePlays', просто возвращая undefined, если один из упомянутые узлы не существуют.

Эквивалентная функция доступна как функция во многих библиотеках. Подчеркнуть * property, loda sh property и Ramda ' s path предлагают несколько разные варианты этого. (Отказ от ответственности: я автор Рамды.) Однако достаточно легко написать нашу собственную:

const getPath = (pathStr) => (obj) =>
  pathStr .split ('.')
    .reduce ((o, p) => (o || {}) [p], obj)

const res = {data: {stats: {home: {teamStats: [{miscellaneous: {offensePlays: "foo"}}]}, away: {teamStats: [{miscellaneous: {offensePlays: "bar"}}]}}}}

const homeTeam = {
  totalPlaysFor: getPath ('data.stats.home.teamStats.0.miscellaneous.offensePlays') (res),
  totalPlaysAgainst: getPath ('data.stats.away.teamStats.0.miscellaneous.offensePlays') (res)
}

console .log (homeTeam)

Обратите внимание, что в этой простой версии массив обозначен не как [0], а как .0. Очевидно, мы могли бы сделать это более изощренным, если это необходимо.

0 голосов
/ 17 февраля 2020

Вы можете деструктурировать столько, сколько хотите!

const homeTeam = {
  totalPlaysFor: res.data.stats.home.teamStats[0].miscellaneous.offensePlays,
  totalPlaysAgainst: res.data.stats.away.teamStats[0].miscellaneous.offensePlays
}

Здесь вы можете даже использовать комбинацию деструктуризации массива / деструктуризации объекта:

const [ home ] = res.data.stats.home.teamStats
const [ away ] = res.data.stats.away.teamStats

const { offensePlays: totalPlaysFor } = home.miscellaneous
const { offensePlays: totalPlaysAgainst } = away.miscellaneous

const hometeam = { totalPlaysFor, totalPlaysAgainst }

Или, если вы хотите более многократно используемое решение, вы можете использовать деструктуризацию параметров:

const getTeam = (
  { miscellaneous: { offensePlays: totalPlaysFor } },
  { miscellaneous: { offensePlays: totalPlaysAgainst } }
) => ({
  totalPlaysFor,
  totalPlaysAgainst
})

Тогда вы можете использовать его как:

const [ home ] = res.data.stats.home.teamStats
const [ away ] = res.data.stats.away.teamStats
const homeTeam = getTeam(home, away)
...