Help us understand the problem. What is going on with this article?

ECMAScript 6でforループは使わずに任意の要素数の配列をつくる

More than 1 year has passed since last update.

新しいArrayクラスのメソッドを用いると、forループは使わずに配列要素が処理できます。ただ、もとになる配列がないとき、必要な要素が納められた配列をどのようにつくればよいか考えなければなりません。

forループでCanvasに描画するサンプルコード

お題にするforループを使った関数がつぎのコード001です(「スタイルと色を適用する」参照)。色相が変化した小さい正方形を、Canvasにタイル状に並べます。引数は小さい正方形の一辺の長さと、縦横に並べる個数です。draw(25, 4)で呼び出すと、Canvasには以下の図001の図形が描かれます。jsdo.itに「Drawing squares on Canvas with for loop」として掲げました。

コード001■forループを使ってCanvasに描画する

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

思いつくのは、Array()コンストラクタで長さを決めてつくった配列に、要素はArray.map()メソッドで加えるやり方です。ところが、返されるのは空の配列です。Array.map()メソッドは、値が(undefinedにしても)代入されていない要素については、コールバックを呼び出さないからです。

new Array(amount).map(() => 0)  // []

Array.fill()メソッドで配列要素を埋める

ECMAScript 6に備わったArray.fill()メソッドメソッドは、引数の値を指定したインデックスに代入します。これで、長さを定めた配列の要素は埋められますから、Array.map()メソッドが呼び出せます。

前掲コード001のfor文を使った処理は、つぎのコード002のようにArrayクラスのメソッドで替えられるのです。jsdo.itにも「ES6: Drawing squares on Canvas with Array methods」を掲げました。

コード002■for文は使わずにArrayクラスのメソッドで処理する

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()メソッドも加わりました。配列型(array-like)あるいは反復可能(iterable)オブジェクトから、新たにArrayインスタンスをつくるのがもともとの役割です。けれどさらに、第2引数にマップのためのコールバック関数が与えられます。そして、第1引数が長さを決めただけの要素のない配列でも、コールバック関数が呼び出せるのです。

前掲コード002は、Array.from()メソッドを使ってつぎのように書き替えることもできます。

// new Array(amount).fill(0, 0).map((data, i) => ({
Array.from(new Array(amount), (data, i) => ({
    // プロパティ
}))

スプレッド演算子で配列要素を分ける

ECMAScript 2015にスプレッド演算子...が備わりました。配列要素を分けて親配列の要素にできるのです。この演算子を使って、前掲コード002はつぎのように書き替えることもできます。

[...new Array(amount)].map((data, i) => ({
    // プロパティ
}))

[2018年1月23日: 本項を追記]

FumioNonaka
はなし家、もの書き、コード書き。詳しくはwebで。 担当講座: 電気通信大学ウェブシステムデザインプログラム「Web UI・UXプログラミング演習I・Ⅱ」 https://www.websys.edu.uec.ac.jp/ ロクナナワークショップ「Vue.js入門講座」 https://67.org/ws/workshop/detail/0136javascript.html
http://www.fumiononaka.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした