for文を使わないでやってみた


はじめに

for文は色々な言語で用意されており、様々なところで使われています。
実際、同じ処理を複数回するときに便利です。
また、for文が使われていれば、容易に繰り返し同じことをしていると分かります。
簡単であり、可読性が高いという点で、for文は優れていると思います。

しかし、それは処理という面で捉えるからです。
オブジェクトという面で見たときは、拡張for文の登場によって扱えるとは言え、優れているとは言えないでしょう。
JavaScriptにはちゃんと Array というビルドインオブジェクトが用意されているので、それを使って繰り返す処理を書くことも選択肢に入れましょう。

という訳で、今回はfor文からArrayを使った書き方に移行する方法を紹介していきたいと思います。

指定回数繰り返す

10回ログに出力します。

// for文
for(let i=0; i<10; i++) {
    console.log('repeat:', i);
}


// Array
[...Array(10)].forEach((_, i) => {
    console.log('repeat:', i);
});

[...Array(10)] のようにすることで、固定長の配列を作成することができます。

ここで使っているのは、 Array.prototype.forEach() です。
与えられた配列の中身を順番に実行して、新しく配列を生成する必要の無い場合は、これを使うことができます。

指定範囲の配列を作成する

1から10までの2つおきの配列を作成します。

// for文
const vFor = [];
for(let i=1; i<=10; i+=2) {
    vFor.push(i);
}
console.log(vFor); // [ 1, 3, 5, 7, 9 ]


// Array
const range = (start: number, stop: number, step: number) => {
    return Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
}
const vArray = range(1, 10, 2);
console.log(vArray); // [ 1, 3, 5, 7, 9 ]

ここで使っているのは、 Array.from() です。
新しく配列を生成したいときに使うことができます。

配列の値それぞれを加工する

5人の国語・数学・英語・理科・社会の5教科の合計得点を計算します。

const scores = [
    { '国語': 85, '数学': 78, '英語': 92, '理科': 62, '社会': 69 },
    { '国語': 23, '数学': 44, '英語': 78, '理科': 44, '社会': 50 },
    { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 },
    { '国語': 31, '数学': 42, '英語': 96, '理科': 49, '社会': 68 },
    { '国語': 70, '数学': 55, '英語': 48, '理科': 89, '社会': 11 },
];

// for文
const vFor = [];
for(const score of scores) {
    vFor.push(score.国語 + score.数学 + score.英語 + score.理科 + score.社会);
}
console.log(vFor); // [ 386, 239, 324, 286, 273 ]


// Array
const vArray = scores.map((score) => {
    return score.国語 + score.数学 + score.英語 + score.理科 + score.社会;
});
console.log(vArray); // [ 386, 239, 324, 286, 273 ]

ここで使っているのは、 Array.prototype.map() です。
Array.prototype.forEach と異なり、与えられた配列の中身を順番に実行して、新しく配列を作成したい場合に、これを使うことができます。

配列の値をまたがって加工して1つの値を作成する

教科ごとの合計得点を計算します。

const scores = [
    { '国語': 85, '数学': 78, '英語': 92, '理科': 62, '社会': 69 },
    { '国語': 23, '数学': 44, '英語': 78, '理科': 44, '社会': 50 },
    { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 },
    { '国語': 31, '数学': 42, '英語': 96, '理科': 49, '社会': 68 },
    { '国語': 70, '数学': 55, '英語': 48, '理科': 89, '社会': 11 },
];

// for文
const vFor = { '国語': 0, '数学': 0, '英語': 0, '理科': 0, '社会': 0 };
for(const score of scores) {
    vFor.国語 += score.国語;
    vFor.数学 += score.数学;
    vFor.英語 += score.英語;
    vFor.理科 += score.理科;
    vFor.社会 += score.社会;
}
console.log(vFor); // { '国語': 295, '数学': 229, '英語': 370, '理科': 326, '社会': 288 }


// Array
const vArray = scores.reduce((previous, score) => {
    return {
        '国語': previous.国語 + score.国語,
        '数学': previous.数学 + score.数学,
        '英語': previous.英語 + score.英語,
        '理科': previous.理科 + score.理科,
        '社会': previous.社会 + score.社会,
    };
}, { '国語': 0, '数学': 0, '英語': 0, '理科': 0, '社会': 0 });
console.log(vArray); // { '国語': 295, '数学': 229, '英語': 370, '理科': 326, '社会': 288 }

ここで使っているのは、 [Array.prototype.reduce()] です。(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) です。
与えられた配列の中身を順番に実行して、1つの値を作成したい場合に、これを使うことができます。

データを基に並列処理を行う

Yahoo! JapanGoogle へリクエスト送信を並列処理で行います。

import fetch from 'node-fetch';

const urls = [
    'https://www.yahoo.co.jp/',
    'https://www.google.com/',
];

// for文
(async () => {
    const promises = [];
    for(const url of urls) {
        promises.push((async () => {
            const response = await fetch(url);
            return await response.text();
        })());
    }
    console.log(await Promise.all(promises));
})();


// Array
(async () => {
    console.log(
        await Promise.all(
            urls.map(async (url) => {
                const response = await fetch(url);
                return await response.text();
            })
        )
    );
})();

リクエストの送信には、 node-fetchを使用しています。
Array側の方が階層は深くなってしまっていますが、書いている内容はシンプルです。
内容としては、 Array.prototype.map() を使って、 Promise が返る配列を作成し、それを Promise.all に渡しています。

(番外編)for...in

教科の一覧を表示します。

const score = { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 };

// for文
for(const key in score) {
    console.log(key);
}


// Array
Object.keys(score).forEach((key) => {
    console.log(key);
});

for...in の書き換えには、 Object.keys() を併用します。
keyの一覧を配列として取得してからは、 Array.prototype.forEach() でも Array.prototype.map() でも Array.prototype.reduce() でも使用することができます。

おわりに

for文とArrayを使った書き方は、どちらがお好みでしょうか?
試しに作っているコードを、for文からArrayへ、Arrayからfor文へ書き直してみてください。