配列メソッドを正しく使用する

5342 ワード

Arrayを使うArrayの代わりにindexOf
「配列内の要素を検索する場合は、Array.indexOfを使用します.」
私がJavaScriptを勉強している授業で似たような言葉があったのを覚えています.間違いなく、これは完全に正しい!
MDNドキュメントでは、Array.indexOfについて、配列内に所与の要素を見つけることができる最初のインデックスを返し、存在しない場合は-1を返します.したがって、その後のコードでインデックスを使用する必要がある場合、Array.indexOfは2つの選択肢ではありません.
しかし、配列に特定の要素が含まれているかどうかを知る必要があります.これは、ブール問題(boolean question)であるかどうかの違いを意味します.この場合、ブール値を直接返すArray.includesを使用することをお勧めします.
'use strict';

const characters = [
  'ironman',
  'black_widow',
  'hulk',
  'captain_america',
  'hulk',
  'thor',
];

console.log(characters.indexOf('hulk'));
// 2
console.log(characters.indexOf('batman'));
// -1

console.log(characters.includes('hulk'));
// true
console.log(characters.includes('batman'));
// false

Arrayを使うArrayの代わりにfilter
Array.filterは非常に有用な方法です.元の配列をコールバック関数でフィルタし、フィルタされたアイテムを新しい配列として返します.その名前が示すように,この方法をフィルタリングに用い,より短い長さの新しい配列を得ることができる(一般的に).
しかし、コールバック関数によってフィルタリングされた後、唯一のものしか残っていないことを知っている場合は、Arrayを使用することをお勧めしません.filter.たとえば、フィルタ条件として一意のIDを使用して配列をフィルタします.この例では、Array.filterは、1つだけの新しい配列を返します.しかし,我々はIDが特定のIDであるものを取得するためだけに,この新しい配列は役に立たないように見える.
パフォーマンスについて議論しましょう.コールバック関数のフィルタ条件を満たすすべてのアイテムを取得するために、Array.filterは配列全体を巡回する必要があります.元の配列に何千もの項目がある場合、コールバック関数が実行される回数はかなり多い.
それを避けるためにArrayを使うことをお勧めします.find.Arrayとfilterもコールバック関数を必要としますが、条件に合致する最初の項目を返します.コールバック関数のフィルタ条件に合致する最初の要素が見つかった場合、すぐに下の検索を停止します.配列全体を巡りません.
'use strict';

const characters = [
  { id: 1, name: 'ironman' },
  { id: 2, name: 'black_widow' },
  { id: 3, name: 'captain_america' },
  { id: 4, name: 'captain_america' },
];

function getCharacter(name) {
  return character => character.name === name;
}

console.log(characters.filter(getCharacter('captain_america')));
// [
//   { id: 3, name: 'captain_america' },
//   { id: 4, name: 'captain_america' },
// ]

console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }


Arrayを使うArrayの代わりにfind
私はよくこの間違いを犯したことを認めます.その後、ある友人はMDNドキュメントを見て、より良い方法を探すことをお勧めします.実際(このエラーは)上のArray.indexOf/Array.includesの例とよく似ています.
上の例ではArrayを知っていますfindはパラメータとしてコールバック関数を必要とし、(条件に合致する)最初の要素を返します.しかし、配列に要素が存在するかどうかを知る必要がある場合、Array.findは最も良い選択ですか?ブール値ではなく要素を返すため、必ずしもそうではありません.
次の例では、Arrayを使用することをお勧めします.some、必要なブール値を返します.

'use strict';

const characters = [
  { id: 1, name: 'ironman', env: 'marvel' },
  { id: 2, name: 'black_widow', env: 'marvel' },
  { id: 3, name: 'wonder_woman', env: 'dc_comics' },
];

function hasCharacterFrom(env) {
  return character => character.env === env;
}

console.log(characters.find(hasCharacterFrom('marvel')));
// { id: 1, name: 'ironman', env: 'marvel' }

console.log(characters.some(hasCharacterFrom('marvel')));
// true


追加して私とアーニーincludesの使用上の違い.両方とも、配列に存在するかどうかを示すブール値を返します.対応する項目が見つかったら、すぐに配列のループを停止します.違うのはアリーsomeのパラメータはコールバック関数であり、Array.includesのパラメータは1つの値です(2番目のオプションパラメータは考慮されません).
値がvalueのアイテムが配列に存在するかどうかを知りたい場合は、コードを記述できます.
[].includes(value),      Array.some    item => item === value 

コールバック関数として使用します.Array.もっと簡単に使えsomeの操作性がより強い.
Arrayを使うArrayの代わりにろ過器とArray.mapの組み合わせ
実はアーリーreduceはあまり理解しにくいです.しかし、Arrayを先に使うとfilterは元の配列をフィルタし、その後(結果に対して)Array.mapを呼び出します(新しい配列を取得します).これは少し問題があるように見えますが、私たちが何を無視しているのでしょうか.
このような問題は、配列を2回巡ったことです.最初は元の配列をフィルタして長さがやや短い新しい配列を取得し、2回目の遍歴(Array.map)は、Array.filterが返す新しい配列を加工し、再び新しい配列を作成したものです!最終的な結果を得るために、2つの配列方法を組み合わせて使用しました.各方法には独自のコールバック関数があり、Array.map用の一時配列はArray.filterによって提供されます.(一般的に)この配列は多重化できません.
このような非効率なシーンを避けるために、Arrayを使用することをお勧めします.reduce .同じ結果、より良いコード!Array.reduceでは、フィルタされたカット加工されたアイテムをアキュムレータに入れることができます.アキュムレータは、インクリメントされるべき数、塗りつぶされるべきオブジェクト、接合される文字列、または配列などであってもよい.
上記の例では、Arrayを使用しています.map、(ただし、さらには)アキュムレータを接合する配列のArray.reduceとして使用することを推奨します.次の例では、変数envの値に基づいて、アキュムレータに追加するか、アキュムレータを一定に維持します(つまり、何も処理しません).
'use strict';

const characters = [
  { name: 'ironman', env: 'marvel' },
  { name: 'black_widow', env: 'marvel' },
  { name: 'wonder_woman', env: 'dc_comics' },
];

console.log(
  characters
    .filter(character => character.env === 'marvel')
    .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
);
// [
//   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
//   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]

console.log(
  characters
    .reduce((acc, character) => {
      return character.env === 'marvel'
        ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
        : acc;
    }, [])
)
// [
//   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
//   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]

注意:Arrayを使用してください.findとArray.includesの前にブラウザが関連メソッドをサポートしているかどうかを確認します.上記の2つのメソッドはインターネットExplorerではサポートされていません(Polyfillを使用できます).