要素を足す・取り除く
このレッスンで分かること
pushで末尾に足し、popで末尾から取り除けますunshiftで先頭に足し、shiftで先頭から取り除けますpushが返すのは配列ではなく、追加後の要素数です
要素を足す・取り除く とは
作った配列はあとから中身を増やしたり減らしたりできます。末尾と先頭に対する 4 つの操作を覚えます。
配列は作ったあとも変えられる
前のレッスンで、山田 太郎さんの作品を配列にまとめました。
const works = ["プロフィールサイト", "自己紹介カード", "スキル一覧の表"];ですがプロフィールサイトは作って終わりではありません。新しい作品ができれば足したいですし、公開をやめた作品は取り除きたい。配列は、作ったあとから中身を変えられる入れ物です。そのための道具が今回の 4 つのメソッドです。
| メソッド | 何をするか | 戻り値 | 例 |
|---|---|---|---|
push | 末尾に足す | 追加後の要素数 | works.push("新作") |
pop | 末尾から取り除く | 取り除いた要素 | works.pop() |
unshift | 先頭に足す | 追加後の要素数 | works.unshift("新作") |
shift | 先頭から取り除く | 取り除いた要素 | works.shift() |
名前が 4 つ出てくると混乱しますが、覚えかたは単純です。push と pop は末尾、unshift と shift は先頭。そして push と unshift が足す側、pop と shift が取り除く側です。
末尾に足す push と末尾から取り除く pop
いちばんよく使うのが push です。配列の末尾に新しい要素を足します。
const works = ["プロフィールサイト", "自己紹介カード"];
works.push("スキル一覧の表");
console.log(works); // ["プロフィールサイト", "自己紹介カード", "スキル一覧の表"]
console.log(works.length); // 3push はカンマで区切って複数まとめて足すこともできます。
const works = [];
works.push("プロフィールサイト", "自己紹介カード");
console.log(works.length); // 2反対に、末尾の要素を取り除くのが pop です。取り除いた要素そのものが戻り値になるので、受け取って使えます。
const works = ["プロフィールサイト", "自己紹介カード", "スキル一覧の表"];
const removed = works.pop();
console.log(removed); // スキル一覧の表
console.log(works.length); // 2空配列に対して pop を呼んでもエラーにはならず、undefined が返るだけです。配列の中身は空のままです。
push の戻り値は配列ではない
ここが今回いちばんの引っかかりどころです。push の戻り値は、追加したあとの要素数です。配列そのものではありません。
const works = ["プロフィールサイト"];
const result = works.push("自己紹介カード");
console.log(result); // 2 (配列ではなく数値)
console.log(works); // ["プロフィールサイト", "自己紹介カード"]push は works という配列そのものを直接書き換えます。ですから戻り値を受け取る必要はなく、works をそのまま使えばよいのです。次のように書いてしまうと、関数が数値を返してしまい、テストが通りません。
function addWork(works, title) {
return works.push(title); // 2 のような数値が返る
}正しくはこうです。
function addWork(works, title) {
works.push(title);
return works; // 配列を返す
}「メソッドを呼んだ結果を返す」という書きかたは多くの場面で正解なので、つい
return works.push(title)と書いてしまいます。ここは JavaScript の配列メソッドの性格を知っているかどうかの差です。配列を書き換える系のメソッドは、書き換えたあとの配列ではなく別の値を返すものが多い、と覚えておいてください。
先頭に足す unshift と先頭から取り除く shift
先頭側の操作も見ておきましょう。unshift は先頭に足し、既にあった要素は 1 つずつうしろにずれます。
const works = ["自己紹介カード", "スキル一覧の表"];
works.unshift("プロフィールサイト");
console.log(works[0]); // プロフィールサイト
console.log(works[1]); // 自己紹介カードshift は先頭を取り除き、取り除いた要素を返します。残りの要素は 1 つずつ前にずれます。
const works = ["下書き", "プロフィールサイト", "自己紹介カード"];
const removed = works.shift();
console.log(removed); // 下書き
console.log(works[0]); // プロフィールサイトpop と同じく、空配列に shift を呼んでも例外は起きません。undefined が返り、配列は空のままです。今回の課題ではこの性質を利用します。
先頭への出し入れは、うしろの要素を全部ずらす必要があるため、末尾への出し入れより処理コストが高くなります。要素が数千を超えるような配列では差が出ますが、画面に並べる程度の件数なら気にしなくて構いません。まずは意味の合うほうを選んでください。
1 手ずつ追ってみる
4 つのメソッドを順に呼んだとき、配列がどう変わるかを書き出します。出発点は ["下書き", "プロフィールサイト"] です。
| 手 | 呼び出し | 呼んだあとの配列 | 戻り値 |
|---|---|---|---|
| 1 | works.push("自己紹介カード") | ["下書き", "プロフィールサイト", "自己紹介カード"] | 3 |
| 2 | works.shift() | ["プロフィールサイト", "自己紹介カード"] | "下書き" |
| 3 | works.unshift("新着") | ["新着", "プロフィールサイト", "自己紹介カード"] | 3 |
| 4 | works.pop() | ["新着", "プロフィールサイト"] | "自己紹介カード" |
足す側の push と unshift は要素数を返し、取り除く側の pop と shift は取り除いた要素そのものを返す。表を横に見ると、この対応がはっきり分かります。
そして 4 つとも、元の works を直接書き換えています。呼び出しの結果を新しい変数に入れなくても、works の中身はもう変わっています。ここが「配列を書き換えるメソッド」の共通の性質です。
使い分けの考えかた
どちらを使うかは「新しいものをどこに置きたいか」で決めます。作品一覧を古い順に並べたいなら新作は push で末尾へ。新しいものを一番上に出したいなら unshift で先頭へ。表示の順番から逆算して選ぶのがコツです。
なお、配列の途中に足したり途中から取り除いたりする splice というメソッドもありますが、引数の意味が独特で間違えやすいため、入門ではあつかいません。まずは先頭と末尾の 4 つを確実に使えるようにしましょう。
よくある間違い
pushの戻り値を配列だと思って返す — 戻り値は数値です。配列を返したいならpushしたあとに配列そのものを返します
function addWork(works, title) {
// return works.push(title); // 数値が返ってしまう
works.push(title);
return works;
}popとshiftを取り違える —popは末尾、shiftは先頭です。名前から向きが読み取りにくいので、表を見返して確認する癖を付けてください
const works = ["A", "B", "C"];
console.log(works.pop()); // C (末尾)
console.log(works.shift()); // A (先頭)- カッコを忘れる —
works.popと書くと関数そのものが返るだけで、何も取り除かれません。メソッドは必ず()を付けて呼びます
const works = ["A", "B"];
works.pop; // 何も起きない
works.pop(); // B が取り除かれる要件
- 関数名は
updateWorkList、引数は配列worksと文字列newTitleの 2 つ、戻り値は配列 - 先頭の要素を
shiftで取り除いてから、newTitleをpushで末尾に足すこと return works.push(newTitle)と書かないこと (pushの戻り値は数値なので配列にならない)
入出力例
updateWorkList([], "プロフィールサイト") → ["プロフィールサイト"]
updateWorkList(["下書き"], "プロフィールサイト") → ["プロフィールサイト"]
updateWorkList(["下書き","自己紹介カード"], "スキル一覧の表") → ["自己紹介カード","スキル一覧の表"]
updateWorkList(["下書き","プロフィールサイト","自己紹介カード"], "スキル一覧の表") → ["プロフィールサイト","自己紹介カード","スキル一覧の表"]