LoginSignup
17
16

JavaScriptは「参照渡し」をしないって本当?

Last updated at Posted at 2023-12-27

概要

タイトルの答えはYES.

JSを勉強し始めたばかりで、JSにおける値渡し/参照渡し/参照の値渡しの処理の違いがわかりませんでした。
調べていくうちに「え、JSって参照渡ししないんだ!?」となったので、ここに学んだことをまとめようと思います。

追記:いただいたコメントをもとに修正しました。コメントありがとうございます!

結論

  • JSでの処理は「プリミティブ値は値渡し」「オブジェクトは参照渡し」と言われていますが、厳密には「参照渡し」はしません。
  • JSでは「参照の値渡し」(共有渡し、本文中では共有渡しに統一)が行われています。

値渡し、参照渡し、共有渡しとは

  • 値渡し
    • 引数に値を渡す時、変数の値をコピーして渡す処理。
      • 呼び出しもとの変数は変化しません。
  • 参照渡し
    • 引数に値を渡す時、参照(=メモリ番地)で渡す処理。
      • 変更が呼び出しもとに反映されます。
  • 共有渡し
    • 引数に値を渡す時、変数に格納されている参照をコピーして渡す処理。
      • 大抵の言語はオブジェクトを渡す時にこの形態になります。
      • 参照渡しと似ているように感じますが、実際には違う動きをします。

JSにおける処理

言葉の意味だけではわかりづらいので、実際に挙動の確認をしてみましょう。
わかりやすいように「プリミティブ値は値渡し」「オブジェクトは参照渡し」と呼ばれているものの処理を比較します。

JSの基本的な処理

値が生成されると、変数aにその参照が割り当てられます。

  • 変数aに値10が渡された時の参照をS1とします。
    • 全てのサンプルコードにおいて、定義後の参照をS1、再代入後の参照をS2と表記しています。
    • サンプルコードは参考記事(下記掲載)の引用です。
  • b = aを定義するとbにはS1が割り当てられます。
    • イメージ的には b → S1 → 10のようなたどり方をします。
var a = 10 // S1
var b = a // bにS1が渡される

console.log(b) // 10

「プリミティブ値は値渡し」と呼ばれているものの処理

var a = 10
var b = a

a = 100

console.log(b) // 10
//解説

var a = 10 // S1
var b = a // bにS1が渡される

a = 100 // 再代入したのでa = 100にS2が割り当てられる

console.log(b) // bにはS1が渡されているのでS1  = 10が成立

「オブジェクトは参照渡し」と呼ばれているものの処理

b = { val: 100 }が成立したことで参照渡しをしているように見えますが、実際は違います。
仮にJSが参照渡しであった場合、S1がS2に変更になります。

var a = { val: 10 }
var b = a

a.val = 100

console.log(b) // { val: 100 }
//解説

var a = { val: 10 } // S1
var b = a // bにS1が渡される

a.val = 100
// value値が100に変更
// 同じオブジェクトを操作しているため、aの参照がS2に変更されたわけではない

// bにはそのままS1が渡される
console.log(b) // { val: 100 }

// 参照渡しではない

おわりに

もし誤りがあれば指摘いただけるとありがたいです。

参考記事

17
16
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16