値型と参照型の違いを考える

はいどーもニートです。
みなさんツクールでオブジェクトをコピーしてますか?
僕はあんまりしてません。

そんなわけで有意義な具体例が思い浮かびませんが、値型と参照型の違いを考えてみたいと思います。

ズバリ参照型とは

例えば「現在のパーティの完全なコピー」を保存したいとしましょう。
このとき、コピー元とコピー先は全く別の存在として管理したいとします(実際にそんなことがあるかどうかはともかく)。
どうしますか?
こうでしょうか

var copy_party = $gameParty;

もし仮にcopy_partyが$gamePartyと完全に独立しているなら、copy_partyの変更は$gamePartyに影響を及ばさないはずです。
実験してみましょう。

var copy_party = $gameParty;
copy_party._steps = 10000;
console.log($gameParty.steps());
//10000

はい、コメントで示した通りです。
結果から、copy_partyと$gamePartyは独立していないことがわかりますね。
つまりオブジェクトは参照型であるため($gamePartyもオブジェクト)、オブジェクトを変数に代入しても、値そのものがコピーされるのではなく、参照先が代入されるのです。
これが何を意味するかと言えば、同じ参照先を示すので、copy_partyへの変更は$gamePartyをも変更することになるのです。

独立したコピーを作りたい場合

独立したコピーを作りたい場合、Object.assign()を使います


var copy_party = Object.assign({}, $gameParty);
console.log('コピー直後' + copy_party._steps);
copy_party._steps = 10000;
console.log('値代入後' + copy_party._steps);
console.log('元の値' + $gameParty.steps());

これで独立したコピーの完成です。

なお、Object.assign()は__proto__など列挙不可のプロパティはコピーしません
つまりcopy_partyを使ってプロトタイプチェーン上に存在するメソッドなどの使用は不可です。

注*補足記事も書きました。ご覧ください。

例えば以下のコードはエラーが出ます。

copy_party.steps();

ズバリ値型とは

今度は値型に行ってみましょう。
先ほどと似たようなコードを書いてみます。

var copy_steps = $gameParty._steps;
console.log(copy_steps);
copy_steps = 10000;
console.log($gameParty._steps);
//結果は?

さっきと同じ理屈でいけば10000だ!
と思った方はハズレです。
1万ではなく、歩いた歩数がそのまんま表示されます。

今回の代入は、参照のコピーではなく値のコピーだからです。
値そのもの(歩数そのもの)を代入しているだけで、参照先を代入しているわけではないのです。
つまり、copy_stepsと$gameParty._stepsは完全に独立しています

「なんで参照型なんてあるんや? ややこいやんけ!」と思うかもしれませんが(僕も思っていた)、これはこれで便利ですし、参照型の方がメモリの効率がよいです(とあるC#の本には「よくわからなければ全て参照型(構造体ではなくクラス)で作ればよい」とまで書いてありました)。

というわけで、慣れれば難しくありませんので、この値型と参照型の違いになれていきましょう!
値型と参照型の違いを知っていなければ、プラグイン製作の思わぬ落とし穴になりかねませんよ!

というわけで、ほなこんな感じで。

フォローする