つばさのーと

つばさの日常を綴るのーと

ES2015を学びつつもES5で追加された配列メソッド10個をおさらいしました

f:id:tsubasa123:20170119171032j:plain

 

こんにちは、つばさ(@tsubasa123)です。

 

ES2015の学習にどっぷりつかっている私ですが、ES5もちゃんと網羅しておきたいよね、ということで知らなくてもなんとかなっていたけど、知っておいた方がよさそうな配列メソッドについて調べました。

 

ざっと調べてみましたが、多分、この記事に書いた10個のメソッドがES5で追加されたものだと思います。抜けや誤認がありましたら教えていただけるとうれしいです。

 

知らなくてもなんとかなるから困る

 

ほんとこれ。新しく追加されたメソッドはどれも非常に便利なものなんですが、知らなくてもコードは書けちゃうんですよね。だからモチベーションが低い時はなかなかやる気がでないものでして。言い訳ですけどね。

 

あと、ブラウザ問題。レガシーブラウザで動かないから~って言い訳してきましたが、IE9以上なら動くっぽいですね。これはもう言い訳に使えない。私の勉強不足でしかありません。

 

私の中のES2015ブームが過ぎ去るまえにざっと確認しておきます。全10種類、一気にいきます。

 

Array.isArray

 

対象のオブジェクトが配列かどうかチェックします。

 

const arr = [1, 2, 3, 4, 5];
console.log(Array.isArray(arr)); // true

 

昔の書き方

 

一昔前はこんな風に書いていました。なげーよ。

 

const arr = [1, 2, 3, 4, 5];
console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

 

Array.prototype.forEach

 

配列の要素数だけ繰り返し処理を行います。コールバックの引数には、要素、インデックス、対象の配列の3つが渡されます。が、大体の処理は第一引数の要素だけで完結すると思います。

 

const arr = [1, 2, 3, 4, 5];
arr.forEach((v, k, a) => {
    console.log(v); // 1, 2, 3...
});

 

昔の書き方

 

当たり前ですがforループでも代用可能ですね。

 

const arr = [1, 2, 3, 4, 5];
for (let i = 0, n = arr.length; i < n; i++) {
    console.log(arr[i]); // 1, 2, 3...
}

 

Array.prototype.map

 

配列の各要素に対して任意の処理を行い値を返すことで、その結果からなる新しい配列を作成します。元の配列には変更は加わりません。すべての要素に処理が適用されるので、新しく作られる配列と元の配列の要素数は同じになります。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.map((v, k ,a) => {
    return v + v;
});
console.log(res); // [2, 4, 6, 8, 10]

 

昔の書き方

 

ループでも代用可能。mapが使えない言語だとこんなコードを書くことが多いと思います。

const arr = [1, 2, 3, 4, 5];
const res = [];
for (let i = 0, n = arr.length; i < n; i++) {
    res.push(arr[i] + arr[i]);
}
console.log(res); // [2, 4, 6, 8, 10]

 

Array.prototype.filter

 

mapと似ていますが、こちらは各要素に対して任意の処理を行い真偽値を返すことで、特定の条件を満たす要素を抽出します。こちらも元の配列には影響しません。任意の要素の抽出なので新しく作られる配列の要素数は必ず元の配列の要素数以下になります。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.filter((v, k, a) => {
    return v % 2 === 0;
});
console.log(res); // [2, 4]

 

昔の書き方

 

これもmapと同じようになります。

 

const arr = [1, 2, 3, 4, 5];
const res = [];
for (let i = 0, n = arr.length; i < n; i++) {
    if (arr[i] % 2 === 0) {
        res.push(arr[i]);
    }
}
console.log(res); // [2, 4]

 

Array.prototype.reduce

 

各処理の実行結果が次の処理の引数として渡されます。コールバック関数の第一引数が実行結果、第二引数が配列の各要素になります。reduce関数への第二引数に初期値を指定することができます。こちらは省略可能となっています。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.reduce((a, v) => {
    return a + v;
}, 0);
console.log(res); // 15

 

昔の書き方

 

ループ処理の外に初期値を宣言し、各ループ処理ごとに値を追加していけば同じことが可能です。

 

const arr = [1, 2, 3, 4, 5]
let res = 0;
for (let i = 0, n = arr.length; i < n; i++) {
    res += arr[i];
}
console.log(res); // 15

 

Array.prototype.reduceRight

 

reduceは配列の先頭から処理が行われますが、こちらは配列の末尾から処理が始まります。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.reduceRight((a, v) => {
    return a + v;
}, 0);
console.log(res); // 15

 

昔の書き方

 

ループを逆にするだけですね。

 

const arr = [1, 2, 3, 4, 5];
let res = 0;
for (let i = arr.length - 1, n = 0; i >= n; i--) {
    res += arr[i];
}
console.log(res); // 15

 

Array.prototype.indexOf

 

配列の要素のうち、一番最初に一致した位置を取得します。一致する要素が配列内に存在しない場合は -1 が返されます。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.indexOf(3);
console.log(res); // 2

 

昔の書き方

 

ループで代用可能です。複数ある場合はループにしなきゃならないのかな。

 

const arr = [1, 2, 3, 4, 5];
let res;
for (let i = 0, n = arr.length; i < n; i++) {
    if (arr[i] === 3) {
        res = i;
        continue;
    }
}
console.log(res); // 2

 

Array.prototype.lastIndexOf

 

indexOfは前方一致ですが、こちらは後方一致になります。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.lastIndexOf(3);
console.log(res); // 2

 

昔の書き方

 

ループを逆に(ry

 

const arr = [1, 2, 3, 4, 5];
let res;
for (let i = arr.length - 1, n = 0; i >= n; i--) {
    if (arr[i] === 3) {
        res = i;
        continue;
    }
}
console.log(res); // 2

 

Array.prototype.some

 

配列要素のうち、どれか1つでも条件を満たすとtrueが返されます。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.some((v) => {
    return v > 3;
});
console.log(res); // true

 

昔の書き方

 

ループの外で真偽値を false で初期化し、ループ内で条件判定を行います。

 

const arr = [1, 2, 3, 4, 5];
let res = false;
for (let i = 0, n = arr.length; i < n; i++) {
    if (arr[i] > 3) {
        res = true;
        continue;
    }
}
console.log(res); // true

 

Array.prototype.every

 

こちらは配列要素の全てが条件を満たすとtrueが返されます。

 

const arr = [1, 2, 3, 4, 5];
const res = arr.every((v) => {
    return v > 3;
});
console.log(res); // false

 

昔の書き方

 

ループの外で真偽値を true で初期化し、ループ内で条件判定を行います。

 

const arr = [1, 2, 3, 4, 5];
let res = true;
for (let i = 0, n = arr.length; i < n; i++) {
    if (arr[i] <= 3) {
        res = false;
        continue;
    }
}
console.log(res); // false

 

さいごに

 

ざっとまとめましたが特に難しいことはないですね。reducemapfilterあたりが活躍する機会が多いんじゃないでしょうか。reduceに関しては結構可能性を感じたのでまた改めて便利な使い方をまとめてみたいところです。

 

ではでは、最後までお付き合いいただきありがとうございました。