Q1const items = ["ペン", "テープ", "メモ"]; のとき、length と最後の要素の index の組み合わせはどれですか?
配列 — 追加・削除・取り出し
複数の商品や作業を 1 つの変数でまとめる配列を、要素の取り出しから追加・削除まで解説します。末尾と先頭への出し入れ、含まれているかの判定、一部の切り出しと差し替えまで押さえます。
カートに入った商品を item1 / item2 / item3 のように別々の変数で持つと、商品が 1 つ増えるたびに変数を足し、件数を数えるコードも書き直す必要があります。配列(複数の値を順番に並べて 1 つの変数で扱うデータ構造)を使うと、何件あっても 1 つの変数で受け取れて、追加や取り消しも配列のメソッドに任せられます。
配列に値を並べる — index と length
配列は [ と ] の中に、値をカンマで区切って並べて作ります。1 つ 1 つの値を 要素(配列に並んでいる値のこと)と呼びます。文字列でも数値でも並べられますが、あとの処理をそろえるため、実務では同じ種類の値を並べます。
並べた要素は index(先頭を 0 として数えた要素の位置)を [] に書いて取り出します。cart[1] = "テープ" と書けば、その位置の要素だけを入れ替えられます。
cart[0] が 1 番目、cart[1] が 2 番目です。1 番目が 0 なので、人が数える順番とは 1 つずれます。
length は要素の個数です。cart.length のように、カッコを付けずに書きます。index は 0 から始まるため、最後の要素の index は length から 1 を引いた値 です。
末尾から数える at(-1) を使うと、length を経由せずに最後の要素を取り出せます。at(-2) なら後ろから 2 番目です。
範囲外の index を読んでもエラーにはならず、値がまだ入っていないことを表す undefined が返ります。
cart.length は 3、最後の index は 2 です。末尾から数える at(-1) は同じ要素を返します。const cart = ["ノート", "ペン", "テープ"];
console.log(cart[0]); // ノート
console.log(cart[2]); // テープ
console.log(cart.length); // 3
// 末尾は length から 1 を引いた index、または at(-1)
console.log(cart[cart.length - 1]); // テープ
console.log(cart.at(-1)); // テープ
// 範囲外の index を読んでもエラーにはならない
console.log(cart[5]); // undefined
末尾と先頭に出し入れする — push / pop / shift / unshift
カートの中身は、商品を足したり取り消したりするたびに変わります。そのたびに配列を書き直していては、件数と index を自分で管理しなければなりません。配列には 末尾と先頭に対して要素を出し入れするメソッド があり、位置の計算はそちらに任せられます。
push(値) は末尾に要素を追加し、追加後の要素数を返します。pop() は末尾の要素を取り除き、取り除いた要素そのもの を返します。
取り消した商品名をそのまま画面に出したいときは、メソッドが返したこの値(返り値)を const removed = cart.pop(); のように変数で受け取ります。
先頭側を扱うのが unshift(値) と shift() です。unshift は先頭に追加し、shift は先頭を取り除きます。先頭に 1 つ入れると、それより後ろの要素の index はすべて 1 つずつ後ろへずれます。
const cart = ["ペン"];
console.log(cart.push("テープ")); // 2 (追加後の要素数)
console.log(cart.join(", ")); // ペン, テープ
console.log(cart.pop()); // テープ (取り除いた要素)
console.log(cart.join(", ")); // ペン
cart.unshift("メモ"); // 先頭に追加
console.log(cart.join(", ")); // メモ, ペン
console.log(cart.shift()); // メモ (取り除いた要素)
console.log(cart.join(", ")); // ペン
const で宣言した cart の中身が変わっている点が気になるかもしれません。const が禁止するのは cart = 別の配列 のように 名前に別の値を入れ直すこと で、cart.push(値) のように配列の中身を書き換えることは止めません。この違いが起きる理由は、あとの記事であらためて扱います。
含まれているかを調べる — includes と indexOf
同じ商品をもう一度お気に入りに入れようとしたとき、そのまま push すると同じ名前が 2 つ並びます。追加する前に、その値がすでに配列にあるかどうかを確かめておくと、重複を防げます。
includes(値) は、その値が配列にあれば true、なければ false を返します。位置まで知りたいときは indexOf(値) を使い、最初に見つかった index を返します。見つからないときは -1 です。
文字列の includes / indexOf と考え方は同じで、探す対象が文字ではなく要素です。
どちらも === と同じように型まで見て比べるので、型が違えば別の値として扱います。数値を並べた配列に文字列の "2" を渡しても、一致とは見なされません。
["メモ", "ボード"] のときの返り値です。有無だけが必要なら includes、位置まで必要なら indexOf です。indexOf は見つからないと -1 を返します。const favorites = ["メモ", "ボード"];
console.log(favorites.includes("メモ")); // true
console.log(favorites.includes("消しゴム")); // false
console.log(favorites.indexOf("ボード")); // 1
console.log(favorites.indexOf("消しゴム")); // -1
// 比べ方は === と同じで、型が違えば別の値
const quantities = [1, 2, 3];
console.log(quantities.includes("2")); // false
indexOf の結果をそのまま条件に置かない
先頭で見つかったときの indexOf の返り値は 0 です。0 は falsy なので、if (favorites.indexOf(name)) と書くと 先頭の要素だけ「無い」と判定 されます。有無を知りたいだけなら includes を使い、indexOf を使うときは !== -1 のように結果を明示的に比べます。
一部を取り出す・入れ替える — slice と splice
売上ランキングの上位 3 件だけを表示したい、便の一覧の途中の 1 件だけを差し替えたい、といった場面があります。ここで分かれるのは、元の配列を残したまま取り出すのか、元の配列ごと書き換えるのか です。
slice(開始, 終了) は、開始の index から終了の 手前 までを取り出した新しい配列を返します。元の配列は変わりません。
終了を省略すると最後までを取り出します。文字列の slice と数え方は同じです。
splice(開始, 削除数, 追加する値) は元の配列そのものを書き換えます。開始の index から削除数の分だけ取り除き、追加する値を書くとその位置に差し込みます。
返るのは 取り除いた要素の配列 なので、1 件だけ取り除いたときは [0] で中身を読みます。
| 書き方 | 返す値 | 元の配列 |
|---|---|---|
| slice(開始, 終了) | 取り出した新しい配列 | 変わらない |
| splice(開始, 削除数) | 取り除いた要素の配列 | 書き換わる |
| splice(開始, 削除数, 追加する値) | 取り除いた要素の配列 | 書き換わる |
const ranking = ["ペン", "テープ", "メモ", "ボード"];
// slice は新しい配列を返し、ranking は変わらない
const top2 = ranking.slice(0, 2);
console.log(top2.join(", ")); // ペン, テープ
console.log(ranking.length); // 4
// splice は ranking 自体を書き換える
const removed = ranking.splice(1, 2, "消しゴム");
console.log(removed.join(", ")); // テープ, メモ
console.log(ranking.join(", ")); // ペン, 消しゴム, ボード
console.log(ranking.length); // 3
slice と splice は 1 文字違いで結果が違う
名前は似ていますが、slice は元の配列を残して新しい配列を返し、splice は元の配列を書き換えます。一覧を表示するためだけに splice を呼ぶと、表示のたびに元のデータが減っていきます。取り出すだけの用途では slice を選びます。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2cart.pop() が返す値はどれですか?
Q3呼んでも元の配列が変わらないのはどれですか?