1. FumioNonaka

    No comment

    FumioNonaka
Changes in body
Source | HTML | Preview
@@ -1,65 +1,76 @@
新しい`Array`クラスのメソッドを用いると、`for`ループは使わずに配列要素が処理できます。ただ、もとになる配列がないとき、必要な要素が納められた配列をどのようにつくればよいか考えなければなりません。
#forループでCanvasに描画するサンプルコード
お題にする`for`ループを使った関数がつぎのコード001です(「[スタイルと色を適用する](https://developer.mozilla.org/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors)」参照)。色相が変化した小さい正方形を、Canvasにタイル状に並べます。引数は小さい正方形の一辺の長さと、縦横に並べる個数です。`draw(25, 4)`で呼び出すと、Canvasには以下の図001の図形が描かれます。jsdo.itに「[Drawing squares on Canvas with for loop](http://jsdo.it/FumioNonaka/Ak47V)」として掲げました。
####コード001■forループを使ってCanvasに描画する
```js
function draw(side, count) {
var context2d = document.getElementById('myCanvas').getContext('2d');
var amount = count * count;
var angle = 360 / (amount - 1);
for (var i = 0; i < count; i++) {
for (var j = 0; j < count; j++) {
context2d.fillStyle = 'hsl(' + angle * (i * count + j) + ', 100%, 50%)';
context2d.fillRect(j * side, i * side, side, side);
console.log(angle * (i * count + j));
}
}
}
```
####図001■色相の変化した正方形がタイル状に並ぶ
![1710002_001.png](https://qiita-image-store.s3.amazonaws.com/0/128949/7ccb9d96-3ffc-b068-302f-c6c21f0c7d78.png)
思いつくのは、`Array()`コンストラクタで長さを決めてつくった配列に、要素は[`Array.map()`メソッド](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map)で加えるやり方です。ところが、返されるのは空の配列です。`Array.map()`メソッドは、[値が(`undefined`にしても)代入されていない要素については、コールバックを呼び出さない](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Description)からです。
```js
new Array(amount).map(() => 0) // []
```
#Array.fill()メソッドで配列要素を埋める
ECMAScript 6に備わった[`Array.fill()`メソッド](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/fill)メソッドは、引数の値を指定したインデックに代入します。これで、長さを定めた配列の要素は埋められますから、`Array.map()`メソッドが呼び出せます。
前掲コード001の`for`文を使った処理は、つぎのコード002のように`Array`クラスのメソッドで替えられるのです。jsdo.itにも「[ES6: Drawing squares on Canvas with Array methods](http://jsdo.it/FumioNonaka/e23i)」を掲げました。
####コード002■for文は使わずにArrayクラスのメソッドで処理する
```js
function draw(side, count) {
const context2d = document.getElementById('myCanvas').getContext('2d');
const amount = count * count;
const angle = 360 / (amount - 1);
new Array(amount).fill(0, 0).map((data, i) => ({
color: `hsl(${angle * i}, 100%, 50%)`,
x: i % count * side,
y: Math.floor(i / count) * side
}))
.forEach((data) => {
context2d.fillStyle = data.color;
context2d.fillRect(data.x, data.y, side, side);
});
}
```
#Array.from()メソッドで新たな要素の配列をつくる
ECMAScript 2015の`Array`クラスには、[`Array.from()`メソッド](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/from)も加わりました。配列型(array-like)あるいは反復可能(iterable)オブジェクトから、新たに`Array`インスタンスをつくるのがもともとの役割です。けれどさらに、第2引数にマップのためのコールバック関数が与えられます。そして、第1引数が長さを決めただけの要素のない配列でも、コールバック関数が呼び出せるのです。
前掲コード002は、`Array.from()`メソッドを使ってつぎのように書き替えることもできます。
```js
// new Array(amount).fill(0, 0).map((data, i) => ({
Array.from(new Array(amount), (data, i) => ({
- // 処理
+ // プロパティ
}))
```
+#スプレッド演算子で配列要素を分ける
+ECMAScript 2015に[スプレッド演算子`...`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_operator)が備わりました。配列要素を分けて親配列の要素にできるのです。この演算子を使って、前掲コード002はつぎのように書き替えることもできます。
+
+```js
+[...new Array(amount)].map((data, i) => ({
+ // プロパティ
+}))
+```
+
+[2018年1月23日: 本項を追記]
+