icon配列(Array)はJavaScriptにおける基本的な要素のひとつです。変数と組み合わせると、初学者にとって少し不可解な挙動をすることがあります。この記事では、配列と変数の組み合わせで発生する不思議な挙動の理由と、その解決方法について説明します。それでも配列をコピーしたいんだけど......基礎と基礎を組み合わせると......バグ?私たちはこう習いました。「変数は値を入れる箱である」と。実際そのように変数は機能します。これは問題ありません。いったことも習いました。「配列は値を入れる箱を複数並べたものである」と。配列は実際そのように機能します。これも問題ないでしょう。これらふたつを組み合わせると、よくわからないことが起こります。両方の内容を表示console.log(array1);console.log(array2);これは簡単なコードです。3]である変数array1と、そのコピーであるarray2を用意します。次にarray1に4という値を追加し、両方の変数を値を表示するだけのものです。3]コードを実際に実行してみましょう。4]おおっと!これはどういうことでしょう?array1には4を追加しましたが、array2には何もしていないはずです。array2にも4が追加されてしまっているようです。不思議な挙動ですが、これはバグではありません。してこういうことが起こるのでしょうか?変数と参照この動きを理解するためには、まず、変数について、ひとつの誤解を解かなければなりません。array1のコピーこのとき、私たちの素朴な理解では、以下の図のようなことが起こっていると考えていました。変数から変数へ配列をコピーする、とても簡単なことです。実はこの図の理解は誤りなのです。実際にはこのようなことは起こっていません。実際にはどうなっているのでしょうか。実は、変数の中に直接配列が入っているわけではありません。変数の中には、「参照」と呼ばれる「配列の場所」が記録されていて、配列の実体は別の場所(メモリ上のどこか)にあります。変数array1は以下の図のようになっています。3]は別の場所(番地1)に存在します。これを変数array2に代入してみましょう!array1の内容をそのままarray2に代入するわけです。すると......ああっと!配列ではなく参照がコピーされてしまいました!そうです、配列自体はコピーされません。参照の値がコピーされるのです。結果として、ふたつの変数は全く同じ配列を指している、ということになります。この状態でarray1を操作してみましょう。array1に4を加えてみます。array1の指し示す配列に4を加えました。array2も同じ配列を指し示しています。4]が見えている、というわけです。これがarray1を操作するとarray2まで変わってしまった現象のカラクリです。まとめると、array1には参照が入っており、array2に代入すると配列ではなく参照がコピーされ、結果としてarray1とarray2は全く同じものを指し示していた、ということになります。関数の引数にも注意これは単なる変数の場合だけではありません。関数の引数にも注意しましょう。4);console.log(a);console.log(b);このとき関数の引数arrayに渡るのも参照の値です。渡された配列の参照をそのまま操作してしまうと、呼び出し元の配列の値まで変わってしまいます。4]関数の中では、むやみに配列を書き換えないようにしましょう。こんなことを?配列が直接変数に入っているわけではないということはわかりました。すると次に疑問に思うのが「なぜこんなことをするのか」でしょう。JavaScriptの値には2種類あります。プリミティブ型とオブジェクト型です。プリミティブ型は数値や文字列といった基本的なもののことで、オブジェクト型は配列(Array)などのその他の値のことです。Arrayオブジェクトに代表されるオブジェクト型は、小さくまとまっているプリミティブ型とは異なり大きな構造を持ちます。Arrayオブジェクトで言えば、複数の値を持てる、多数のメソッドが存在する、多数のプロパティが存在する、などです。いった大きな構造を持つ値を毎回コピーしていると、どうしても処理に時間がかかり、遅くなってしまいます。参照の値を受け渡しするのならば、簡単な値のコピーだけで済むので、短時間で処理を終わらせることができます。この方式の方が、無駄が少ないのです。この参照の値を渡す手法は、Arrayオブジェクトだけでなく、オブジェクト型全てで適用されます。プリミティブでない値を扱うときは気をつけましょう。それでも配列をコピーしたいんだけど......そうは言っても配列をコピーしたい場合というのはよくあります。配列を複製する方法を、いくつか紹介しましょう。ひとつは、Array.fromメソッドを使うことです。これは、他の配列などから、新しい配列を作るメソッドです。Array.fromに配列を渡すことで、内容をコピーした、新しい配列を作ることができます。ひとつは、スプレッド演算子を使うことです。スプレッド演算子を使えば、新しい配列の中に、他の配列の値を展開することができます。[...array];これらの方法を使えば、全く新しい、参照の値も異なる配列を作ることができます。どちらも大した違いはないので、好きな方を使ってください。v1で独自のHTML要素を定義するJavaScriptでも単体テストを導入しよう!ってかテストって何?RSSプロフィール古都ことふるみやことです。フロントエンドとかいろいろやるよ。