JavaScriptのパラメータ渡しはしばしば混乱の的となり、参照渡しなのか値渡しなのかと議論されることが多いです。実際はもっと微妙で、関わるデータ型によって値渡しと参照渡しの両方の側面を組み合わせたメカニズムを採用しています。
目次
プリミティブ型での値渡しについて
JavaScriptのプリミティブデータ型(number
、string
、boolean
、null
、undefined
、bigint
、symbol
)は値渡しによって動作します。プリミティブ型が関数に渡されると、その値のコピーが作成され、渡されます。関数内での変更はそのコピーのみに影響し、元の変数は変更されません。
let x = 10;
function changeValue(y) {
y = 20;
}
changeValue(x);
console.log(x); // 出力: 10
この例では、changeValue
内でy
を変更しても、元のx
は変わりません。
オブジェクトでの参照渡しについて
JavaScriptのオブジェクト(配列や関数を含む)は異なる動作をします。オブジェクトが関数に渡されると、渡されるのは参照、つまりオブジェクトのメモリ位置へのポインタです。そのため、関数内でオブジェクトのプロパティに対して行われた変更は、元のオブジェクトに直接影響します。
let myArray = [1, 2, 3];
function modifyArray(arr) {
arr.push(4);
}
modifyArray(myArray);
console.log(myArray); // 出力: [1, 2, 3, 4]
ここでは、関数がオブジェクト自体を変更するため、myArray
は変更されます。
しかし、重要な違いがあります。関数内でパラメータを*新しい*オブジェクトに再代入しても、元のオブジェクトは変更されません。
let myObject = { a: 1 };
function reassignObject(obj) {
obj = { a: 2 }; // 新しいオブジェクトへの代入
}
reassignObject(myObject);
console.log(myObject); // 出力: { a: 1 }
reassignObject
内では、obj
は異なるオブジェクトを指しています。元のmyObject
は変更されていません。
JavaScriptにおける値渡しと参照渡しの調和
JavaScriptのパラメータ渡しは、厳密にはどちらか一方ではありません。文脈依存のシステムです。
- プリミティブ型: 値渡し。値のコピーが渡されます。内部の変更は元には影響しません。
- オブジェクト: 参照渡し。オブジェクトへの参照が渡されます。オブジェクトのプロパティへの変更は元へ影響します。関数内でパラメータを新しいオブジェクトに再代入しても、元は変更されません。
この違いを理解することは、堅牢で予測可能なJavaScriptコードを書くために不可欠です。動作は、プリミティブ型を扱っているかオブジェクトを扱っているかによって完全に異なります。