私は JavaScript 変数を付箋のように考えています。付箋は、冷蔵庫に貼る小さなメモです。付箋に何が書ける?小さな情報を書き込むことができます。
JavaScript には、プリミティブ値と参照値の 2 種類の情報があります。プリミティブ値は、付箋に直接書き込むことができる小さな情報です。それらには以下が含まれます:
- ブール値
- 数字
- ストリングス
- ヌル
- 未定義
一方、参考値は小さな付箋に書ききれないほどの情報量です。では、参照値を付箋に保存するにはどうすればよいでしょうか。
あなたはそうしない。
参照値 (配列、オブジェクト、関数など) は大きな紙に書かれ、それらへの参照のみが付箋に書かれます。たとえば、妻は次のように書いています。
ハニー、食料品のリストはキーボードの下にあります。
ここで、食料品のリストは配列です (つまり、大量の情報)。小さな付箋に書くことはできないので、大きな紙に書いて、どこにあるかを示す付箋を作るだけです. プログラミング用語では:
var groceryList = ["1 apple", "2 bananas", "3 loaves of bread"];
ここでは、実際の食料品リストがメモリのどこかに保存され、食料品リストのアドレスのみが変数に保存されますgroceryList
。
では、ある変数を別の変数に代入するとどうなるでしょうか? まず、プリミティブ値の例を見てみましょう。
var x = 2;
var y = x;
alert(y); // 2
y = 3;
alert(x); // 2
これが起こっていることです:
2
新しい付箋に番号を書いて、冷蔵庫に貼ります。
2
番号を付箋x
から別の付箋にコピーしy
て、冷蔵庫に貼り付けます。
- 付箋の値を消去し、代わりに
y
番号を書き込みます。3
- 現在、付箋の値は であり、付箋
x
はです。2
y
3
x
これは、付箋の値を付箋にコピーしているだけなので、値によるコピーと呼ばれますy
。
次に、参照によるコピーの例を見てみましょう。実際、参照によるコピーの例を見てみましょう:
var objA = {a: 1};
var objB = objA;
objA.a = 2;
objB.a; // 2
あなたの例で起こっていることは次のとおりです。
- メモリのどこかにオブジェクトを作成し、
{a: 1}
このオブジェクトのアドレスを付箋に書きobjA
ます。x
簡単にするために、このアドレスを呼びましょう。
x
付箋objA
から別の付箋に住所をコピーしますobjB
。と の両方が、メモリ ロケーション に保存されている同じオブジェクトobjA
を参照するようになりました。objB
{a: 1}
x
- したがって、変更する
objA.a
と同じ変更の値が反映されます。これは、との両方がメモリ ロケーション に保存されている同じオブジェクトを参照するobjB.a
ためです。objA
objB
x
オブジェクトの参照を付箋から付箋に単純にコピーしているため、これは参照によるコピーと呼ばれobjA
ますobjB
。実際のオブジェクトをコピーしているわけではありません。
では、参照によるコピーと値によるコピーの違いは何でしょうか? 何もない。どちらの場合も、ある付箋の値を別の付箋にコピーしているだけです。
2 つの付箋は、まったく同じ情報が含まれている場合にのみ、同等であると言われます。たとえば、以下は同等です。
var x = 2;
var y = 2;
alert(x === y); // true
var o = {a: 1};
var p = o;
alert(o === p); // true
ただし、次の値は同等ではありません。
var o = {a: 1};
var p = {a: 1};
alert(o === p); // false
それらが等しくない理由は、別のメモリ ロケーション say に格納されているオブジェクトを指しているのに対しo
、メモリ ロケーション sayに格納されているオブジェクトを指すためです。これらのオブジェクトはどちらもまったく同じプロパティを持っていますが、実際には 2 つの異なるオブジェクトです。x
p
y
たとえば、任天堂のゲームボーイは、見た目がどれだけ同じでも、同じものは 2 つとありません。同じ精神で、最後の例を見てみましょう。
var objA = {a: 1};
var objB = objA;
objA = {a: 2}; //Assigned whole object here instead property.
objB.a; //1 - Shouldn't this be 2 ??
上記のコードで何が起こっているかを次に示します。
{a: 1}
メモリの場所にオブジェクトを作成しx
、アドレスx
を付箋に書きobjA
ます。
x
アドレスを付箋から付箋objA
にコピーしますobjB
。どちらも現在、メモリ ロケーション に保存されている同じオブジェクトを指していますx
。
{a: 2}
メモリの場所に新しいオブジェクトを作成しy
、アドレスy
を棒のメモに書き込みますobjA
。現在objA
は参照値があり、参照値y
がありobjB
ますx
。これらは 2 つの異なるオブジェクトを参照します。
ご覧のとおり、新しい参照値を に割り当てると、objA
単に古い参照値が上書きされます。{a: 1}
objectをobject に置き換えません{a: 2}
。これは JavaScript では不可能です。