TL;DR
・代入元がObject型だった場合、引数には参照元のアドレスが格納される
はじめに
この記事の経緯としては、
下記記事を見ていたらこんなことが書かれていたから
3歳娘「パパ、もう参照渡しの話はやめて?」
ワイ「関数の中で配列aに要素を追加したり、一部を編集したりした場合は外のaにも変更が>反映されるけど」
ワイ「丸ごと上書きしてもうた場合は別もんになるから、外のaには影響なしや」
なんで丸ごと上書きした場合は別物になるのかが分からなかった。
というのがきっかけ
よく分からんからソース書いて
・ 分かる
(function(){
let ary = new Array(0,0,0,0,0,0,0,0);
f(ary);
console.log("ary:"+ary);
}());
function f(obj){
obj = "aaa";
}
ary:0,0,0,0,0,0,0,0
・ 分からん
(function(){
let ary = new Array(0,0,0,0,0,0,0,0);
f(ary);
console.log("ary:"+ary);
}());
function f(obj){
obj[0] = "aaa";
}
ary:aaa,0,0,0,0,0,0,0
調べた結果
で調べているうちに下記記事を見つけた
JavaScriptはオブジェクトについて参照渡しだなんて、信じない
これを見て、引数がオブジェクト型の時の挙動が思っていたのとは違った
今までは引数に配列を渡すと配列の値を直接いじっていると思っていたが、
ここに入っているものはあくまで参照元のアドレスのコピーが入っているっぽい
確かにそう考えるとすっきりする
試す
そもそもこれは別に関数の引数だけに限ったことではなく・・・
・ 例1
(function(){
let val1 = {id:"123",name:"val1"};
//val1のアドレスをval2に渡す
val2 = val1;
//id書き換え
val2.id = "456";
console.log(val1.id);
console.log(val2.id);
}());
val1:456
val2:456
・ 例2
(function(){
let val1 = {id:"123",name:"val1"};
//val1のアドレスをval2に渡す
val2 = val1;
//プロパティ追加
val2.from = "japan";
console.log("val1:"+val1.from);
console.log("val2:"+val2.from);
}());
val1:japan
val2:japan
・例3
(function(){
let val1 = {id:"123",name:"val1"};
//val1のアドレスをval2に渡す
val2 = val1;
//val2に文字列を代入
val2 = "書き換え";
console.log("val1:"+val1);
console.log("val2:"+val2);
}());
val1:[object Object]
val2:書き換え
・例4
(function(){
let val1 = {id:"123",name:"val1"};
//val1のアドレスをval2に渡す
val2 = val1;
val1 = "";
console.log("val1:"+val1);
console.log("val2:"+val2);
}());
これで参照元のObjectは潰したし、val2も参照できなくなるやろ・・・
val1:
val2:[object Object]
なくならんやんけ・・・・・・・・・・
この辺は多分メモリーリークとかに関連する話で、
JavaScriptにはガベージコレクションというその変数が使用されなくなると自動的に
メモリを開放してくれる仕組みがあるが、val2がそのオブジェクトをまだ使っている!
みたいな判定をしているので現段階ではまだメモリ上にあのオブジェクトが残っているという・・・
まぁここは今回関係ないから今度また・・・
まとめ
引数がオブジェクトの場合アドレスが格納されているので、
添え字やプロパティーで代入先を指定した場合には変更が適用される。
何も指定せずまるっと変更した場合は元々入っていたアドレスが消える為
オブジェクトの変更が適用されない
参考URL
3歳娘「パパ、もう参照渡しの話はやめて?」
JavaScriptはオブジェクトについて参照渡しだなんて、信じない
JavaScriptに参照渡し/値渡しなど存在しない