音ゲー、fps、DTM、プログラミング雑記置き場

ブログタイトル通りに雑記を垂れ流す。

【JavaScript】代入`a = b`で何がaに入る?

  • 結論から言うと、bの値への参照情報
    • 参照渡しじゃんとなるけど、アドレスを渡しているかまで
      言語仕様理解してないのであくまで「実値への参照情報」
    • JavaScriptがそもそも高級よりでメモリとか関与してなさそうだから
      渡してるのはアドレスな気がする。(これは自分の意見)
  • 下記記事と主張は同じ。またソースの一部を引用させていただいています。
  • JavaScriptに参照渡し/値渡しなど存在しない

    • プリミティブ値が値渡し、それ以外が参照渡しという意見(事実かも)を
      見るが、JavaScriptに他言語のような値渡し、参照渡しを行う構文が
      用意してないよう見受けられるため上記記事の認識のが自分はしっくりきた
    • VB系列やC#にはRef,Valみたいなこれは値渡しの
      変数だよという構文がある)
  • 参照させていただいた記事内のソース+自分で手を加えたやつで
    「実値への参照」が入る論を紐解いていく

  • パターン1(プリミティブな値の代入)

var a = 10;
var b = a;
a = 100;
console.log(a); //??
console.log(b); //??
  • aは3ステップ目で100が代入されているので「100」が出力
  • bは2ステップ目でa(10への参照)が代入されているので「10」が出力
  • イメージ図は下図

  • パターン2(プリミティブでない値の代入)
var a = {val:10};
var b = a;
a.val = 100;
console.log(a); //??
console.log(b); //??
  • aは1ステップ目でオブジェクトへの参照(object→val→10)までが入り、
    3ステップ目でオブジェクト内の値valの参照先が100に変更される
    • valへの参照はオブジェクトでラップされているため
      そのオブジェクトを参照しているaも「100」となる
  • baが持つオブジェクトへの参照が同じく入るので「100」が出力
  • イメージ図は下図(TODO:Objectも色分けした方がいい)

シャローコピー、ディープコピーはどうして起こるか

  • 上記認識だと、ここのコピー問題もどうして起きるのかが説明しやすい

  • シャローコピー例

    • 下記のような単純な代入だけでなく、object.assing()等の
      オブジェクト操作系のメソッドでもシャローコピーとなる
let obj = {"A":1, "B":2, "C":3};
//単純な代入はシャローコピーとなる
let objCopy = obj;
//コピー先の要素を変更する
objCopy['A'] = 4;
console.log(JSON.stringify(obj)); // {"A":4,"B":2,"C":3}
console.log(JSON.stringify(objCopy)); // {"A":4,"B":2,"C":3}
  • パターン2と同様でコピー先にはコピー元の参照情報が入るので、
    宣言したオブジェクトの変更が両方に影響する
  • イメージ図は下図

  • ディープコピー例
    • コピー時に参照情報が入らないように、コピー元を明示的に複製して、
      複製したものを代入すればコピー元の参照は影響がなくなる
let obj = {"A":1, "B":2, "C":3};
//JSON変換→パースを行うことでオブジェクトを明示的に複製する
let objCopy = JSON.parse(JSON.stringify(obj));
//コピー先の要素を変更する
objCopy['A'] = 4;
console.log(JSON.stringify(obj)); // {"A":1,"B":2,"C":3}
console.log(JSON.stringify(objCopy)); // {"A":4,"B":2,"C":3}
  • objCopyJSON形式のテキストデータから新規作成されるため、
    copyへの参照情報は入らない
    • 互いに別オブジェクトとして扱える
  • イメージ図は下図

結論

  • パターン1,2より=による代入は右辺の実値への参照情報
    が入る認識がしっくりくる