はじめに
プログラミング言語において参照やコピーは基礎の基礎。しかし私はJavaScriptを書いていてよく混乱することが多いので整理のためにも、参照とコピーについてまとめたいと思います。
プリミティブ型とオブジェクトの参照
まずはプリミティブ型とオブジェクトの参照についてみていきます。
//プリミティブ型の参照
let num = 1;
num = 2;
console.log(num); // 2
//オブジェクト型の参照
let obj = {
a: "hello",
}
obj.a = "world";
console.log(obj.a); // world
プリミティブ型の参照は、変数num
に1が記録されたメモリのアドレスが代入されています。この状態を『参照』と言い、そして変数num
に2を再代入する時は、1が記録されていたメモリに2が上書きされ参照先自体は変わりません。
オブジェクトの参照は、obj
に"hello"が格納されたメモリのアドレスを参照するa
が保持されていることになります。なのでオブジェクトは『データをキーと値のペアで管理するもの』と定義されることがありますが、『データのアドレスに名前をつけて管理するもの』とも言えます。
参照とコピー
次に参照とコピーとその注意点についてです。
下記のコードでは変数num
の値を変数num2
にコピーしnum2
の値を変更しています。
//プリミティブ型の参照
let num = 1;
let num2 = num;
num2 = 2;
console.log(num); // 1
console.log(num2); // 2
//オブジェクト型の参照
let obj = {
a: "hello",
}
let obj2 = obj;
obj2.a = "world";
console.log(obj.a); // world
console.log(obj2.a); //world
ここでコピーされたnum
とnum2
の値を確認すると値が違います。num
からnum2
へコピーした時は、num
の参照先の値をコピーし複製した新しい参照先のものがnum2
へ保持されています。
しかし、オブジェクト型の参照の実行結果を見ると出力結果が同じになっています。
これはobj
からobj2
へ値を代入する際の挙動に差異があるからです。
オブジェクトを新しくコピーしようとした際にプリミティブ型のように新しいものが複製されるのではなく、参照先が同じオブジェクトが作成されているのです。つまり、オブジェクトの名前が違うだけで参照する値は同じものになります。
このようにプリミティブ型とオブジェクト型の参照とコピーには差異があり、この違いをしっかりと理解していないとJavaScriptを学んでいく中でつまづくことが多くなってしまいます(私のことです)。
参照と引数
ここからが非常に面白く、実は上記で説明させていただいた参照とコピーは関数へ引数を渡す際も同様のことが起きています。
// プリミティブ型を引数として渡す
let name = "marumoto";
function updateName(nameA) {
console.log(nameA); // marumoto
nameA = "shoma";
console.log(nameA); // shoma
};
updateName(name);
console.log(name); // marumoto
// オブジェクトを引数として渡す
let user = {
name: "marumoto",
}
function updateUserName(userA) {
console.log(userA.name); // marumoto
userA.name = "shoma";
console.log(userA.name); // shoma
};
updateUserName(user);
console.log(user.name); // shoma
ここでの両者の違いも同様に
- プリミティブ型の値を関数へ渡した時は、関数スコープ内で使用する変数は引数として受け取った変数とは違う変数
- オブジェクトを関数へ渡した時は、参照先のアドレスが渡されるので引数として渡ってきたものと同じオブジェクト
という参照とコピーの法則が適用されるようになります。
最後に
いかがだったでしょうか、今回は私がJavaScriptを勉強していて理解が難しかった参照とコピーについてまとめてみました。
同じように見えるものでも実は背景では違うものとして扱われていて、とても分かりにくいとは思いますが、ここを理解しておくとバグを防ぐことができるのでしっかりと意識していきたいところだと思っています。
GoQSystemでは一緒にはたらいてくれる仲間を募集中です!
ご興味がある方は以下リンクよりご確認ください。