--- title: 配列 slug: Learn/JavaScript/First_steps/Arrays tags: - CodingScripting - JavaScript - Join - Pop - Push - 'l10n:priority' - shift - split - unshift - 初心者 - 学習 - 記事 - 配列 translation_of: Learn/JavaScript/First_steps/Arrays ---
このモジュールの最後に、配列について見ていきましょう。配列は 1 つの変数名でリスト形式のデータを保持するのに好都合です。ここでは、どう便利なのか、どのように作るのか、そして配列の項目を追加したり削除したり取得したりする方法について学びます。
前提条件: | 基礎的なコンピューターの知識、HTML と CSS への基本的な理解、JavaScript についての理解。 |
---|---|
目的: | JavaScript において、配列とは何か、どのように操作するのかを理解する。 |
配列はたいてい「リストのようなオブジェクトである」と説明され、単一のオブジェクト内に複数の値をリストとして持っています。配列オブジェクトは変数に格納され、その他の型と同様に扱われます。異なるのはリスト内の値に個別にアクセスすることができ、繰り返しを用いて全ての値に同じことをするといった、リストとして便利で効率的に扱うことができます。商品とその価格の一覧を配列に保持し、その値をループして合計額を計算しつつ請求書にそれぞれの価格を表示して一番下に合計額を表示することもできるでしょう。
もし配列がなかったとしたら、別々の変数にそれぞれの値を格納しなければならず、各変数を表示するのと計算するので別々に呼び出さなければならなかったでしょう。こうなると、書き出すのがとても長く、非効率的でエラーを起こしやすいプログラムとなるでしょう。例えば、10 個の項目を請求書に出すだけでも最悪ですが、それが 100 個や 1000 個だったらどうでしょう。この記事の最後に実例としてやってみましょう。
前回までの記事と同様に、JavaScript コンソールに配列の基礎となるコード例をブラウザーの開発者コンソールに入力しながら学びましょう。
配列を作るには、角括弧の中にカンマで区切ったリストの形式で項目を並べます。
let shopping = ['パン', '牛乳', 'チーズ', 'ハム', '麺']; shopping;
let sequence = [1, 1, 2, 3, 5, 8, 13]; let random = ['tree', 795, [0, 1, 2]];
配列の各項目は文字列中の文字を取得したときのように列で角括弧 ([]
) を使用して取得することができます。
shopping[0]; // "パン"という値が戻ります
shopping[0] = 'タヒーニ'; shopping; // ショッピングリストは[ "タヒーニ", "牛乳", "チーズ", "ハム", "麺" ]に変更されています。
random
変数に格納された配列の 3番目の項目のさらに 3番目の項目を取得するには以下のようにします。
random[2][2];
ある配列の長さ (いくつの項目が配列中に存在するか) を知るには、文字列の (文字の) 長さを調べた時と全く同じようにします。{{jsxref("Array.prototype.length","length")}}プロパティを使用して長さを取得することができます。
sequence.length; // 7 が返る
このプロパティはいろいろな使われ方をするのですが、最もよく使われるのは、配列中の全項目をループするために使用されます。次の例を見てください。
let sequence = [1, 1, 2, 3, 5, 8, 13]; for (let i = 0; i < sequence.length; i++) { console.log(sequence[i]); }
ループについてはそのうち (Looping code の記事で) しっかりと学ぶ機会があるでしょうが、ここで簡単に説明すると上のコードは次のように動きます。
console.log()
メソッドを使用してブラウザーのコンソールに出力しています。このセクションでは、文字列を配列にしたり、配列を文字列にしたり、配列に項目を追加したり、ちょっと便利な配列関連のメソッドを見てみましょう。
データが長い長い文字列の中に含まれていて、それを使いやすい形に分割して操作したいときがあります。例えばデータを表形式で表示するというようなときです。それには{{jsxref("String.prototype.split()","split()")}} メソッドが使用できます。このメソッドは文字列を分割するのに使用する文字を引数として取り、文字列をその文字で区切った部分文字列の配列に分割します。
注: 実際のところ、これは配列ではなく文字列のメソッドです。しかし、ここで紹介するのが一番だと思い取り上げています。
let myData = '札幌,仙台,東京,名古屋,大阪,博多';
let myArray = myData.split(','); myArray;
myArray.length; myArray[0]; // 配列の最初の項目 myArray[1]; // 配列の二番目の項目 myArray[myArray.length-1]; // 配列の最後の項目
let myNewString = myArray.join(','); myNewString;
toString()
は join()
と比べ簡単でしょうが、制限があります。join()
を使えば、他の区切り文字を指定することもできます (4. の例をカンマ以外の他の文字を指定して試してください)。
let dogNames = ['ポチ','ハチ','タロウ','モコ']; dogNames.toString(); //ポチ,ハチ,タロウ,モコ
まだ配列への項目の追加と削除をやっていませんでしたね。次はこれをやりましょう。先ほどの例にあった myArray
配列を使用します。先ほどの例をまだ実行していなければ、以下のコードをコンソールに入力して配列を作ってください。
let myArray = ['札幌', '仙台', '東京', '名古屋', '大阪', '博多'];
まず、配列の最後に項目を追加したり、最後の項目を削除するには、それぞれ {{jsxref("Array.prototype.push()","push()")}} と {{jsxref("Array.prototype.pop()","pop()")}} を使います。
push()
を使ってみます。配列の最後に項目を追加するには 1 つ以上の項目を引数に指定します。
myArray.push('横浜'); myArray; myArray.push('神戸', '広島'); myArray;
let newLength = myArray.push('京都'); myArray; newLength;
pop()
を呼び出すだけです。
myArray.pop();
let removedItem = myArray.pop(); myArray; removedItem;
{{jsxref("Array.prototype.unshift()","unshift()")}} と {{jsxref("Array.prototype.shift()","shift()")}} はそれぞれ push()
や pop()
と同様の動作ですが、配列の末尾ではなく先頭において動作します。
unshift()
を次のように実行します。
myArray.unshift('奈良'); myArray;
shift()
でやってみましょう!
let removedItem = myArray.shift(); myArray; removedItem;
商品の名前と価格、合計金額を請求書に印字するという最初の話に戻りましょう。以下に示す編集可能なコードのコメントの中に数字が書かれています。この数字はコードを書くべき場所を示しています。各数字の場所に次のようなコードを書いてください。
// No.1
というコメントの下に、商品の名前と価格をコロン (:) で繋げた、いくつか文字列が並んでいます。これを products
という名前の配列にしてください。// No.2
というコメントの行から for ループが始まっています。この行には i <= 0
と書かれています。「i
の値が 0 以下でなくなれば終了」と書かれており、i
は 0 から始まるので、この for ループは一度しか実行されません。この条件を i
が products
配列の長さより小さくなくなった場合に終了するような条件に置き換えて下さい。// No.3
のコメントの直下に 1 行で、現在の配列の項目 (name:price
) を 2 つに分割するコードを書いてください。一方は商品の名前、もう一方は価格です。もしどうすればいいのかわからなければ、便利な文字列のメソッドの記事を参照してください。さらに{{anch("Converting between strings and arrays","文字列と配列を相互に変換する")}}も役に立つでしょう。total
という名前の変数が宣言されて、0 で初期化されています。ループの中で (// No.4
の下) 繰り返している現在の項目の価格を total
変数に加算するコードを一行で書いてください。そうすれば、コードの最後で正しい合計が請求書に印字されます。恐らく代入演算子が役に立つでしょう。// No.5
のコメントの直下のコードを itemText
変数が「現在の項目の商品名 — $現在の項目の価格」となるように変更してください。「靴 — $23.99」という感じです。そうすれば正しい情報が請求書に印字されます。これはもう慣れたはずの単純な文字列結合で実現できます。<h2>出力結果</h2> <div class="output" style="min-height: 150px;"> <ul> </ul> <p></p> </div> <h2>コードエディター</h2> <p class="a11y-label">コードエディターから抜けるには Esc キーを押して下さい(タブキーではタブ文字を挿入します)。</p> <textarea id="code" class="playable-code" style="height: 410px;width: 95%"> const list = document.querySelector('.output ul'); const totalBox = document.querySelector('.output p'); let total = 0; list.innerHTML = ''; totalBox.textContent = ''; // No.1 'パンツ:6.99' '靴下:5.99' 'T シャツ:14.99' 'ズボン:31.99' '靴:23.99'; for (let i = 0; i <= 0; i++) { // No.2 // No.3 // No.4 // No.5 let itemText = 0; const listItem = document.createElement('li'); listItem.textContent = itemText; list.appendChild(listItem); } totalBox.textContent = '合計: $' + total.toFixed(2); </textarea> <div class="playable-buttons"> <input id="reset" type="button" value="リセット"> <input id="solution" type="button" value="答えを見る"> </div>
const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); let code = textarea.value; let userEntry = textarea.value; function updateCode() { eval(textarea.value); } reset.addEventListener('click', function() { textarea.value = code; userEntry = textarea.value; solutionEntry = jsSolution; solution.value = 'Show solution'; updateCode(); }); solution.addEventListener('click', function() { if(solution.value === '答えを見る') { textarea.value = solutionEntry; solution.value = '答えを隠す'; } else { textarea.value = userEntry; solution.value = '答えを見る'; } updateCode(); }); const jsSolution = 'const list = document.querySelector(\'.output ul\');\nconst totalBox = document.querySelector(\'.output p\');\nlet total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nlet products = [\'パンツ:6.99\',\n \'靴下:5.99\',\n \'T シャツ:14.99\',\n \'ズボン:31.99\',\n \'靴:23.99\'];\n\nfor(let i = 0; i < products.length; i++) {\n let subArray = products[i].split(\':\');\n let name = subArray[0];\n let price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n let listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'合計: $\' + total.toFixed(2);'; let solutionEntry = jsSolution; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); // タブキーでテキストエリアから抜けてしまうのを防ぎ、 // 代わりにカーソル位置にタブ文字を挿入する textarea.onkeydown = function(e){ if (e.keyCode === 9) { e.preventDefault(); insertAtCaret('\t'); } if (e.keyCode === 27) { textarea.blur(); } }; function insertAtCaret(text) { const scrollPos = textarea.scrollTop; const caretPos = textarea.selectionStart; const front = (textarea.value).substring(0, caretPos); const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); textarea.value = front + text + back; caretPos = caretPos + text.length; textarea.selectionStart = caretPos; textarea.selectionEnd = caretPos; textarea.focus(); textarea.scrollTop = scrollPos; } // ユーザーがテキストエリアのコードを書き換える度に userCode を毎回更新する textarea.onkeyup = function(){ // ユーザーのコードが表示されているときのみ状態を保存し、 // 答えのコードでユーザーコードが上書きされないようにする if(solution.value === '答えを見る') { userEntry = textarea.value; } else { solutionEntry = textarea.value; } updateCode(); };
html { font-family: sans-serif; } h2 { font-size: 16px; } .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } body { margin: 10px; background-color: #f5f9fa; }
{{ EmbedLiveSample('Playable_code', '100%', 730, "", "", "hide-codepen-jsfiddle") }}
{{jsxref("Array.prototype.push()","push()")}} や{{jsxref("Array.prototype.pop()","pop()")}} といったメソッドを使用するよい例は、ウェブアプリでデータの中で有効な項目だけを抜き出して維持したいときなどです。例えば、アニメーションのあるシーンで、現在表示中の背景イメージを保持している配列があり、一度に表示するイメージをパフォーマンスなどの理由で 50 に制限したいとします。その際、新しいオブジェクトを配列に追加したと同時に、古いオブジェクトを削除して配列を希望のサイズに維持します。
次の例では、もう少し単純に、検索ボックスのある、ダミーの検索サイトを用意しました。検索ボックスに文字が入力されたら、直前 5 つの検索語がリストに表示されます。検索された語が 5 を超えたら最後の検索語が削除されるようになります。新しい検索語が先頭に追加されるので、常に 5 つの検索語が表示されます。
注: 本当の検索アプリでは、前回の検索語をクリックすることでその検索に戻れて、実際に検索結果が表示されることでしょう!ただし、今は単純にしておきましょう。
アプリを完成させるには...
// No.1
コメントの下に、検索ボックスに入力された検索語を配列の先頭に追加するコードを書いてください。検索語は searchInput.value
と書いて取得します。// No.2
コメントの下に、配列の最後の項目を削除するコードを書いてください。<h2>出力結果</h2> <div class="output" style="min-height: 150px;"> <input type="text"><button>検索</button> <ul> </ul> </div> <h2>コードエディター</h2> <p class="a11y-label">コードエディターから抜けるには Esc キーを押して下さい(タブキーではタブ文字を挿入します)。</p> <textarea id="code" class="playable-code" style="height: 370px; width: 95%"> const list = document.querySelector('.output ul'); const searchInput = document.querySelector('.output input'); const searchBtn = document.querySelector('.output button'); list.innerHTML = ''; let myHistory = []; searchBtn.onclick = function() { // 検索ボックスが空ではない場合のみ検索語を受け付けるようにします if (searchInput.value !== '') { // No.1 // 表示中の一覧を空にして、同じ項目が表示されないようにして、 // 結果は検索語が入力される度に毎回作り直されます。 list.innerHTML = ''; // 配列をループして、リスト内の全ての検索語を表示します for (let i = 0; i < myHistory.length; i++) { itemText = myHistory[i]; const listItem = document.createElement('li'); listItem.textContent = itemText; list.appendChild(listItem); } // 配列の長さが 5以上になったら一番古い検索語を削除します if (myHistory.length >= 5) { // No.2 } // 次の検索語を受け付けるため、検索ボックスを空にしてフォーカスします searchInput.value = ''; searchInput.focus(); } } </textarea> <div class="playable-buttons"> <input id="reset" type="button" value="リセット"> <input id="solution" type="button" value="答えを見る"> </div>
html { font-family: sans-serif; } h2 { font-size: 16px; } .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } body { margin: 10px; background: #f5f9fa; }
const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); let code = textarea.value; let userEntry = textarea.value; function updateCode() { eval(textarea.value); } reset.addEventListener('click', function() { textarea.value = code; userEntry = textarea.value; solutionEntry = jsSolution; solution.value = 'Show solution'; updateCode(); }); solution.addEventListener('click', function() { if(solution.value === '答えを見る') { textarea.value = solutionEntry; solution.value = '答えを隠す'; } else { textarea.value = userEntry; solution.value = '答えを見る'; } updateCode(); }); const jsSolution = 'const list = document.querySelector(\'.output ul\');\nconst searchInput = document.querySelector(\'.output input\');\nconst searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nlet myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(let i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n const listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; let solutionEntry = jsSolution; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); // タブキーでテキストエリアから抜けてしまうのを防ぎ、 // 代わりにカーソル位置にタブ文字を挿入する textarea.onkeydown = function(e){ if (e.keyCode === 9) { e.preventDefault(); insertAtCaret('\t'); } if (e.keyCode === 27) { textarea.blur(); } }; function insertAtCaret(text) { const scrollPos = textarea.scrollTop; const caretPos = textarea.selectionStart; const front = (textarea.value).substring(0, caretPos); const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); textarea.value = front + text + back; caretPos = caretPos + text.length; textarea.selectionStart = caretPos; textarea.selectionEnd = caretPos; textarea.focus(); textarea.scrollTop = scrollPos; } // ユーザーがテキストエリアのコードを書き換える度に userCode を毎回更新する textarea.onkeyup = function(){ // ユーザーのコードが表示されているときのみ状態を保存し、 // 答えのコードでユーザーコードが上書きされないようにする if(solution.value === '答えを見る') { userEntry = textarea.value; } else { solutionEntry = textarea.value; } updateCode(); };
{{ EmbedLiveSample('Playable_code_2', '100%', 700, "", "", "hide-codepen-jsfiddle") }}
この記事の最後に到達しましたが、最も大事な情報を覚えていますか?移動する前に、情報を維持しているか検証するテストを見ることができます — Test your skills: Arrays を見てください。
この記事を読んで、配列がとても使えるものであることがお分かりいただけたのではないでしょうか。配列は JavaScript の至るところで見かけます。特に配列の各項目に対して同じことをする際にループと一緒に使われます。便利なループの基本については次のモジュールで教えますが、今は自分自身を褒めて、十分に休みましょう!このモジュールのすべての記事をやり終えました!
ただし、次のモジュールの前に、理解度を確認するため、このモジュールの課題をやりましょう。残っているのはそれだけです。
Array
オブジェクトのリファレンスページです。詳細なガイドと機能については、このリファレンスページで紹介されています。{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}