JavaScriptの値渡しとオブジェクト型の参照について
JavaScriptでオブジェクト型とプリミティブ型について、※1「オブジェクト型は参照渡し/共有渡し」、「プリミティブ型は値渡し」という話を目にするので、自分なりに調べてみました。
※1: 厳密には、参照の値渡しという内容のことのようです。
オブジェクト型とプリミティブ型
JavaScript のほぼすべてのオブジェクトが Object のインスタンスです。
一般的なオブジェクトは、プロパティを(メソッドを含めて) Object.prototype から継承していますが、これらのプロパティはシャドウ化(別名オーバーライド)されている場合があります。
メソッドを持たないデータのことです。 7 種類のプリミティブデータ型があります。
文字列
数値
長整数
論理値
undefined
シンボル
null
値渡し
プリミティブ型の値渡しについてですが、値をコピーして渡し、別の変数として独立して扱われます。
//プリミティブは値をコピーして渡し、別の変数として独立して扱われる
const myBasket = "マイバスケット";
let myRedBasket = myBasket;
myRedBasket="赤いマイバスケット";
console.log(myBasket);//マイバスケット
console.log(myRedBasket);//赤いマイバスケット
参照渡し/共有渡し参照の値渡し
オブジェクトの参照・共有渡し参照の値渡しについてですが、オブジェクトは参照値がコピーされて変数に代入され、複数の変数が同じオブジェクトを参照することになり、オブジェクトの内容を変更すると、他の変数から見た内容も変わるということのようです。
参考:
引数は常に値渡しであり、決して参照渡しではありません。これは、関数が引数に再代入を行っても、関数外では値が変更されないということです。より正確には、オブジェクト引数は共有渡しです。つまり、オブジェクトのプロパティが変更される場合、その変更は関数外にも影響するということです
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions#引数の受け渡し
//オブジェクト型の変数
const itemSample = {
data:
[
{
no: 1,
name: "apple"
},
{
no: 2,
name: "banana"
},
{
no: 3,
name: "cherry"
}
]
}
// itemfruits にitemSample.dataを格納
let itemfruits = itemSample.data;
console.log('itemfruits格納後(変更前)', itemfruits);
//[{"no":1,"name":"apple"},{"no":2,"name":"banana"},{"no":3,"name":"cherry"}]
// itemfruits は itemSample.data と同じ配列への参照値が代入
itemfruits[1].name = "orange";
console.log('itemfruits変更後', itemfruits);
console.log('itemSample.data', itemSample.data);
//[{"no":1,"name":"apple"},{"no":2,"name":"orange"},{"no":3,"name":"cherry"}]
// itemfruits も itemSample.data 配列への参照値を保持している
気付かないうちに、オブジェクトを変数に入れてその変数を使ったら元の値が変わってた、なんてことも自分は起きました。
オブジェクトを他の変数と独立させて扱うには、ディープコピーという手段があるようです。
この辺も、次回まとめたいと思います。
Discussion
参照渡しは、オブジェクトへの参照を渡してオブジェクトを共有することではなく、変数への参照を渡して変数を共有することです。
JavaScriptは変数を共有できないので参照渡しできない言語です。
あと、プリミティブ型がデータをコピーするとは限らないです。
実装次第ですが、JavaScript V8エンジンでは、文字列はコピーせずに共有してメモリ節約してます。
@shiracamus
ありがとうございます。
記事拝見しました。
また、MDNリンクありがとうございます。
JavaScriptでは参照渡し(変数の共有)ではなく、参照の値渡し(値渡しの一種、call by object, call by object-sharing)ということで、参照値が値としてコピーされる、ということかと思いました。
またJavaScript V8の部分もありがとうございます。こちらも調べて加筆修正いたします。
また何かありましたら、コメントいただけますと幸いです。