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

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

JavaScriptの配列操作 - map

JavaScriptには配列を操作できるメソッド(map, filter, some, …)が多く存在する。

現在はReactで開発しているが、JavaScriptの配列操作は頻繁に発生する。今回は、配列を操作するメソッドがどのように動作するのか元の配列へどのような影響があるのか詳しく見ていく。

map

mapメソッドは配列の全ての要素に対して引数に渡された関数を呼び出し、その結果を要素とした新しい配列を生成する。

以下はnames配列に対して各要素に名字を付与しnewNamesという新しい配列を生成している。

const names = ['taro', 'jiro', 'saburo'];
const newNames = names.map(name => `sato ${name}`);

console.log('names:', names);
console.log('newNames:', newNames);

// 結果
// names: ['taro', 'jiro', 'saburo']
// newNames: ['sato taro', 'sato jiro', 'sato saburo']

新しい配列を返すため当然newNamesを操作してもnamesの要素に変更はない。

const names = ['taro', 'jiro', 'saburo'];
const newNames = names.map(name => `sato ${name}`);

// namesを操作
names[3] = 'shiro';

console.log('names:', names);
console.log('newNames:', newNames);

// 結果
// names: ['taro', 'jiro', 'saburo', 'shiro']
// newNames: ['sato taro', 'sato jiro', 'sato saburo']

第一引数のコールバック関数で要素に対して何も操作がない場合でも新しい配列が生成される。

const names = ['taro', 'jiro', 'saburo'];
// 要素をそのまま返す
const newNames = names.map(name => name);

console.log(names === newNames);

// 結果
// false

引数

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

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

// アロー関数
map((element) => {});
map((element, index) => {});
map((element, index, array) => {});
map((element, index, array) => {});

// コールバック関数
map(callback);
map(callback, thisArg);

// インライン
map(function(element){});
map(function(element, index){});
map(function(element, index, array){});
map(function(element, index, array){}, thisArg);

callbackFncの引数は

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

↓callbackFncの引数の確認

const names = ['taro', 'jiro', 'saburo'];
const newNames = names.map((name, index, array) => {
    console.log('name:', name);
    console.log('index:', index);
    console.log('array:', array);
});

// 結果
// name: taro
// index: 0
// array: ['taro', 'jiro', 'saburo']
// name: jiro
// index: 1
// array: ['taro', 'jiro', 'saburo']
// name: saburo
// index: 2
// array: ['taro', 'jiro', 'saburo']

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

callbackFncの引数を確認した例ではconsole.log()のみで戻り値はなかった。この場合、新しく生成される配列は全ての要素が undefined となってしまう。以下MDN参照。

mapは、与えられた callbackFn関数を配列の順番通りに、各要素に対して一度ずつ呼び出し、その結果から新しい配列を生成します。

関数の結果から配列を生成 とあるため戻り値がない場合はundefinedが返される。

const names = ['taro', 'jiro', 'saburo'];
const newNames = names.map((name, index, array) => {});
console.log(newNames);

// 結果
// [undefined, undefined, undefined]

第二引数でthisをバインドする

第二引数のthisArgを指定することでそれがcallbackFncのthisとなる。例ではobjオブジェクトのプロパティとしてfuncメソッドが定義されており、その中でmapメソッドを使用して自身のオブジェクトのnameプロパティを表示している。

const obj = {
    name: 'takumi',
    func: () => {
        [1,2,3].map(function() {
            console.log('name is',this.name);
        })
    }
}

obj.func();

// 結果
// name is
// name is
// name is

mapメソッド中のfunction()のthisはwindowを指すため、nameプロパティは存在せず undefined となる。objのnameプロパティにアクセスしたい場合はmapの第二引数にobjを指定する。

const obj = {
    name: 'takumi',
    func: () => {
        [1,2,3].map(function() {
            console.log('name is',this.name);
        }, obj) // <= objを指定
    }
}

obj.func();

// 結果
// name is takumi
// name is takumi
// name is takumi

参考

JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 - Qiita

this - JavaScript | MDN