概要: このチュートリアルでは、JavaScriptにおける2つの異なる値の型(プリミティブ値と参照値)について学びます。
JavaScriptには2つの異なる型の値があります。
- プリミティブ値
- 参照値
プリミティブ値はアトミックなデータであり、参照値は複数の値で構成される可能性のあるオブジェクトです。
スタックメモリとヒープメモリ
変数を宣言すると、JavaScriptエンジンは、スタックとヒープの2つのメモリ領域にそれらのためのメモリを割り当てます。
静的データとは、コンパイル時にサイズが固定されているデータのことです。静的データには以下が含まれます。
静的データはサイズが変化しないため、JavaScriptエンジンは固定量のメモリ空間を静的データに割り当て、スタックに保存します。
たとえば、次の例では、2つの変数を宣言し、その値をリテラル文字列と数値に初期化します。
let name = 'John';
let age = 25;
Code language: JavaScript (javascript)
name
とage
はプリミティブ値であるため、JavaScriptエンジンはこれらの変数を次の図に示すようにスタックに保存します。
JavaやC#を含む多くのプログラミング言語では文字列はオブジェクトであることに注意してください。ただし、JavaScriptでは文字列はプリミティブ値です。
スタックとは異なり、JavaScriptはオブジェクト(および関数)をヒープに保存します。JavaScriptエンジンは、これらのオブジェクトに固定量のメモリを割り当てません。代わりに、必要に応じてより多くのスペースを割り当てます。
次の例では、name
、age
、およびperson
変数を定義します。
let name = 'John';
let age = 25;
let person = {
name: 'John',
age: 25,
};
Code language: JavaScript (javascript)
内部的には、JavaScriptエンジンは次の図に示すようにメモリを割り当てます。
この図では、JavaScriptは、name
、age
、およびperson
の3つの変数のためにスタックにメモリを割り当てています。
JavaScriptエンジンは、ヒープメモリに新しいオブジェクトを作成します。また、スタックメモリ上のperson
変数をヒープメモリ上のオブジェクトにリンクします。
このため、person
変数はオブジェクトを参照する参照であると言えます。
動的なプロパティ
参照値を使用すると、いつでもプロパティを追加、変更、または削除できます。例:
let person = {
name: 'John',
age: 25,
};
// add the ssn property
person.ssn = '123-45-6789';
// change the name
person.name = 'John Doe';
// delete the age property
delete person.age;
console.log(person);
Code language: JavaScript (javascript)
出力
{ name: 'John Doe', ssn: '123-45-6789' }
Code language: CSS (css)
参照値とは異なり、プリミティブ値はプロパティを持つことができません。これは、プリミティブ値にプロパティを追加できないことを意味します。
JavaScriptでは、プリミティブ値にプロパティを追加できます。ただし、それは効果がありません。例:
let name = 'John';
name.alias = 'Knight';
console.log(name.alias); // undefined
Code language: JavaScript (javascript)
出力
undefined
Code language: JavaScript (javascript)
この例では、alias
プロパティをname
プリミティブ値に追加します。しかし、name
プリミティブ値を介してalias
プロパティにアクセスすると、undefined
が返されます。
値のコピー
ある変数から別の変数にプリミティブ値を割り当てると、JavaScriptエンジンはその値のコピーを作成し、それを変数に割り当てます。例:
let age = 25;
let newAge = age;
Code language: JavaScript (javascript)
この例では
- まず、新しい変数
age
を宣言し、その値を25
で初期化します。 - 次に、別の変数
newAge
を宣言し、age
をnewAge
変数に割り当てます。
内部的には、JavaScriptエンジンはプリミティブ値25
のコピーを作成し、それをnewAge
変数に割り当てます。
次の図は、割り当て後のスタックメモリを示しています。
スタックメモリ上では、newAge
とage
は別々の変数です。一方の変数の値を変更しても、他方には影響しません。
例:
let age = 25;
let newAge = age;
newAge = newAge + 1;
console.log(age, newAge);
Code language: JavaScript (javascript)
ある変数から別の変数に参照値を割り当てると、JavaScriptエンジンは参照を作成し、両方の変数がヒープメモリ上の同じオブジェクトを参照するようにします。これは、一方の変数を変更すると、他方に影響することを意味します。
例:
let person = {
name: 'John',
age: 25,
};
let member = person;
member.age = 26;
console.log(person);
console.log(member);
Code language: JavaScript (javascript)
仕組み。
まず、person
変数を宣言し、name
とage
の2つのプロパティを持つオブジェクトでその値を初期化します。
次に、person
変数をmember
変数に割り当てます。メモリ内では、次の図に示すように、両方の変数が同じオブジェクトを参照します。
3番目に、member
変数を介してオブジェクトのage
プロパティを変更します。
person
とmember
の両方の変数が同じオブジェクトを参照しているため、member
変数を介してオブジェクトを変更すると、person
変数にも反映されます。
まとめ
- JavaScriptには、プリミティブ値と参照値の2つの型の値があります。
- 参照値にはプロパティを追加、変更、または削除できますが、プリミティブ値ではできません。
- ある変数から別の変数にプリミティブ値をコピーすると、個別の値のコピーが作成されます。これは、一方の変数の値を変更しても、他方には影響しないことを意味します。
- ある変数から別の変数に参照をコピーすると、2つの変数が同じオブジェクトを参照するような参照が作成されます。これは、一方の変数を介してオブジェクトを変更すると、別の変数にも反映されることを意味します。