つよつよエンジニアになりたい

つよつよエンジニアになりたいエンジニアが日々の学びや気づきをアウトプットしていきます

JavaScriptの配列操作 filter

filterメソッドは、引数に渡された関数の結果がtruthy(真値)の時の配列の要素を抽出した新しい配列を返します。

truthyはfalsy(false0-00n""nullundefinedNaN)以外の値のことです。

// 3以上の要素を抽出
const arr = [1,2,3,4,5]
const newArr = arr.filter(a => a >= 3);
console.log(newArr);

// 結果
// [3, 4, 5]

新しい配列を返すためnewArrを操作してもarrには影響はありません。

const arr = [1,2,3,4,5]
const newArr = arr.filter(a => a);

newArr[0] = 100;
console.log(newArr);
console.log(arr);

// 結果
// [100, 2, 3, 4, 5]
// [1, 2, 3, 4, 5]

引数

map同様、第一引数は配列の要素を操作するためのコールバック関数(callbackFn)で、第二引数はコールバック関数(thisArg)で使用するthisの値となっています。

第一引数はアロー関数、コールバック関数、インラインコールバック関数での指定が可能です。

// アロー関数
filter((element) => { /* … */ } )
filter((element, index) => { /* … */ } )
filter((element, index, array) => { /* … */ } )

// コールバック関数
filter(callbackFn)
filter(callbackFn, thisArg)

// インラインコールバック関数
filter(function(element) { /* … */ })
filter(function(element, index) { /* … */ })
filter(function(element, index, array){ /* … */ })
filter(function(element, index, array) { /* … */ }, thisArg)

callbackFnの引数は

  • element→処理中の配列要素
  • index→処理中の配列要素の添字
  • array→処理している配列

↓callbackFnの引数の確認

const numbers = [1,2,3];
const filteredNumbers = numbers.filter((number, index, array) => {
    console.log('number', number);
    console.log('index', index);
    console.log('array', array);
});

// 結果
// number 1
// index 0
// array [1, 2, 3]
// number 2
// index 1
// array Array [1, 2, 3]
// number 3
// index 2
// array [1, 2, 3]

callbackFncの戻り値の有無による配列の結果

MDN参照

テストに合格した要素がない場合は、空の配列が返されます。

戻り値がない場合は要素数が0になります。

const numbers = [1,2,3];
const filteredNumbers = numbers.filter(number => {});
console.log(filteredNumbers);
console.log(filteredNumbers.length);

// 結果
// []
// 0

新しく生成される配列はシャローコピー

filterメソッドによって生成された配列は元の配列のシャローコピーになります。

以下のような場合は要素のオブジェクトの参照は同じになるため新しい配列の要素を更新すると元の配列にも更新がかかります。

const users = [
    { id: 1, name: 'takumi', age: 23 },
    { id: 2, name: 'taro', age: 34 } ,
    { id: 3, name: 'yamada', age: 19 },
];
const newUsers = users.filter(user => user.id > 1);

// 新しく生成された配列を更新
newUsers[0].name = 'igarashi';

console.log(newUsers);
console.log(users);

// 結果
// newUsers↓
// 0: {id: 2, name: 'igarashi', age: 34}
// 1: {id: 3, name: 'yamada', age: 19}
// users↓
// 0: {id: 1, name: 'takumi', age: 23} 
// 1: {id: 2, name: 'igarashi', age: 34} ← nameが変更されている
// 2: {id: 3, name: 'yamada', age: 19}

これを防ぐためにはディープコピーしたものをfilterにかける必要があります。

const users = [
    { id: 1, name: 'takumi', age: 23 },
    { id: 2, name: 'taro', age: 34 } ,
    { id: 3, name: 'yamada', age: 19 },
];
const deepCopyUsers = users.map(user => ({...user}));
const newUsers = deepCopyUsers.filter(user => user.id > 1);

参考

developer.mozilla.org