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

# はじめに

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

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

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

# 指定回数繰り返す

10回ログに出力します。

```.ts
// 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()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) です。
与えられた配列の中身を順番に実行して、新しく配列を生成する必要の無い場合は、これを使うことができます。

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

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

```.ts
// 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()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/from) です。
新しく配列を生成したいときに使うことができます。

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

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

```.ts
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()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) です。
`Array.prototype.forEach` と異なり、与えられた配列の中身を順番に実行して、新しく配列を作成したい場合に、これを使うことができます。

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

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

```.ts
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! Japan](https://www.yahoo.co.jp/) と [Google](https://www.google.com/) へリクエスト送信を並列処理で行います。

```.ts
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](https://www.npmjs.com/package/node-fetch)を使用しています。
Array側の方が階層は深くなってしまっていますが、書いている内容はシンプルです。
内容としては、 [Array.prototype.map()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) を使って、 `Promise` が返る配列を作成し、それを `Promise.all` に渡しています。

# （番外編）for...in

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

```.ts
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()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) を併用します。
keyの一覧を配列として取得してからは、 `Array.prototype.forEach()` でも `Array.prototype.map()` でも `Array.prototype.reduce()` でも使用することができます。

# おわりに

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