JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptは値渡し?参照渡し?オブジェクトの挙動をわかりやすく解説

JavaScriptは基本的に「値渡し(pass by value)」の言語です。ただし、オブジェクトの場合、その「値」とはオブジェクトへの参照(リファレンス)を指します。

この仕組みを理解すると、関数に値やオブジェクトを渡したときの挙動の違いが明確になります。まずは、数値(プリミティブ型)を関数に渡した場合の例を見てみましょう。

例1:数値を関数に渡した場合

let i = 0;
function increment(x) {
    x = x + 1
    console.log(x)
}
increment(i)
console.log(i)

出力結果

1
0

この例では、関数内で変数xの値を+1していますが、呼び出し元の変数i0のまま変わっていません。これは、数値などのプリミティブ型が「値そのもの」のコピーとして渡されるためです。関数内での変更は、あくまでコピーに対する操作であり、元の変数には影響しません。

例2:オブジェクトを関数に渡した場合

次に、オブジェクトを渡した場合の挙動を見てみましょう。ポイントは以下の2点です。

  • 関数内で参照そのものを別のオブジェクトに差し替えても、元のオブジェクトには影響しない
  • 関数内でオブジェクトの内部(プロパティなど)を変更すると、元のオブジェクトにも反映される
let obj = {'foo': 'bar'};
function updateRef(x) {
    // xのローカルな参照が更新されるだけで、objには影響しない
    x = {}
}
function addHelloWorld(y) {
    // yが参照しているオブジェクトに新しいプロパティを追加
    y['hello'] = 'world';
}
console.log(obj)
updateRef(obj)
console.log(obj)
addHelloWorld(obj)
console.log(obj)

出力結果

{ foo: 'bar' }
{ foo: 'bar' }
{ foo: 'bar', hello: 'world' }

結果の解説

1つ目の関数updateRefでは、ローカル変数xに空のオブジェクトを再代入しただけなので、元のobj何も変化していません。これは、xが持っていたのは「参照のコピー」であり、そのコピーを上書きしても元の参照には影響しないためです。

一方、2つ目の関数addHelloWorldでは、yobjと同じオブジェクトを参照していました。そこでプロパティhelloを追加すると、同じ実体を共有しているため、元のobjにも変更が反映されます。

まとめ

JavaScriptにおける引数の受け渡しは、常に「値のコピー」です。ただし、オブジェクトの場合、その値とは「参照」であるため、次のように整理できます。

  • プリミティブ型(数値・文字列・真偽値など):値のコピーが渡されるため、関数内での変更は呼び出し元に影響しない
  • オブジェクト(配列・関数なども含む):参照のコピーが渡されるため、内部のプロパティを変更すると呼び出し元のオブジェクトにも反映される。ただし、変数自体を再代入しても元には影響しない

この挙動の違いを理解しておくと、意図しないバグを防ぎ、より安全なコードを書くことにつながります。

  1. JavaScriptのRegExp(正規表現)オブジェクトとは?基本の使い方をわかりやすく解説

    RegExp(正規表現)オブジェクトは、テキストに対してパターンマッチングを行い、目的の文字列部分を検索・抽出するために使用されます。JavaScriptでは、RegExpオブジェクトを「RegExpコンストラクタ」または「リテラル構文」の2通りの方法で作成できます。 RegExpオブジェクトの作成方法 コンストラクタを使用する場合: new RegExp(pattern) リテラル構文を使用する場合: /pattern/ 主なメソッド test():文字列がパターンに一致するかどうかを真偽値(true / false)で返します。 exec():パターンに一致した文字列を返します。

  2. JavaScriptのオブジェクト初期化子とは?使い方をサンプルコードで解説

    オブジェクト初期化子とは オブジェクト初期化子(Object Initializer)は、新しく生成したオブジェクトを初期化するための式です。波括弧 {} の中に、「プロパティ名」と「それに対応する値」のペアを0個以上、カンマ区切りで列挙して記述します。 これにより、変数宣言と同時にオブジェクトの中身を簡単に定義することができます。 以下は、JavaScriptでオブジェクト初期化子を使用したサンプルコードです。 サンプルコード <!DOCTYPE html> <html lang="en"> <head> <meta chars