【初心者向け】JavaScriptの値渡しと参照渡しについて

記事タイトルとURLをコピーする

はじめに

みなさん、始めましたサーバーワークス、アプリケーションサービス部のウルフです🐺

本記事ではJavaScriptにおける値渡しと参照渡しについて解説したいと思います。

そして、最近話題のstructuredClone()についても紹介します。


「値渡し」と「参照渡し」の基礎

JavaScriptにおいて関数の引数に渡される値は「値渡し」と「参照渡し」の2つの方法で渡されます。

値渡し(Pass by Value)

値渡しとは、値そのものをコピーして渡す方法です。引数に渡された変数の値を変更しても、元の変数に影響はありません。

値渡しとは、値そのものをコピーして渡す方法です。引数に渡された変数の値を変更しても、元の変数に影響はありません。

let num = 10; 

function changeNumber(x) {
  return x = 20;
}

changeNumber(num);

console.log(num); // 10
  • 元の変数 num に影響はない。

参照渡し(Pass by Reference)

参照渡しとは、変数のメモリ上のアドレスをコピーして渡す方法です。引数に渡された変数の値を変更すると、元の変数にも影響を与えます。

let obj = {name: 'Alice'};

function changeName(o) {
  o.name = 'Bob';
}

changeName(obj);

console.log(obj.name); // 'Bob' 
  • 元のobj変数nameキーが上書きされる。

JavaScriptではプリミティブ型(文字列、数値、真偽値など)は値渡しで渡され、オブジェクトや配列などのオブジェクト型は参照渡しで渡されます。

以上が値渡しと参照渡しの違いです。


structuredCloneについて

みなさん、structuredClone()ってご存知ですか?私は最近知りました。

これまで、多段にネストされたオブジェクトのコピーの場合、JSON化したものをパースしてコピーやLodashのDeepCloneで対応していました。

※ 以下、例

const obj = {
    name: 'Alice',
    age: 30,
    address: {
        country: 'Japan',
        zip: '123-0001'
        city: 'Tokyo',
    }
}

const copiedObj = JSON.parse(JSON.stringify(obj)) // 元の変数`obj`も`copiedObj`それぞれ独立したオブジェクトとなります。

上記の様なネストされたオブジェクトをスマートにコピーしてくれるのがstructuredClone()です。

structuredCloneの基本的な使い方

structuredCloneを使うことで、オブジェクトの深いコピー(Deep Copy)を実現することができます。 以下は、structuredClone関数を使った例です。

function deepClone(object) {
  return structuredClone(object);
}

let x = { value: 10 };
let y = deepClone(x);
x.value = 20;
console.log(y.value); // 10
  • この場合、deepClone関数はstructuredClone関数を使って、オブジェクトを深くコピーしています。 そのため、xの値を変更しても、yの値は変わりません。

structuredCloneの高度な使い方

structuredClone()は、許可されたデータ型*1以外のオブジェクトはコピーできません。 しかし、以下のようにDataCloneError例外をキャッチして、独自のコピー処理を実装することができます。

function customClone(obj) {
  try {
    return structuredClone(obj);
  } catch (e) {
    if (e instanceof DataCloneError) {
      // 独自のコピー処理を実装する
    } else {
      throw e;
    }
  }
}

structuredCloneの注意点

オブジェクトの制約

  • 関数やSymbol、WeakMap、Promise、プロトタイプ付きのオブジェクトなど、一部のオブジェクトはコピーできない。 #Supported types

パフォーマンスの影響

  • structuredClone()は、オブジェクトの複製を行うため、処理に時間がかかります。
  • 大きなオブジェクトをコピーする場合に注意。

データの機密性

  • structuredClone()は、オブジェクトをコピーするため、データの機密性に影響を与える可能性があります。

実装環境

  • structuredClone()を実装できる環境としては、Service Workerをサポートしている最近のWebブラウザであればほとんどサポートされているようですが、Node.jsでサーバーサイド構築する場合はVersion 17.0.0からのサポートとなっています。 #ブラウザーの互換性

以上の点に注意し、structuredClone()を使って便利なオブジェクトコピーを実現しましょう!


「値渡し」と「参照渡し」の使い分け

「値渡し」を使うべき場面

  • 関数内で引数の値を変更しても、元の変数に影響を与えたくない場合:値渡しを使うことで、関数内で引数の値を変更しても、元の変数に影響を与えず、値そのものがコピーされるため、コードの安全性が向上します。

  • 関数の戻り値として新しい値を返したい場合:値渡しを使うことで、関数の戻り値として新しい値を返すことができます。

「参照渡し」を使うべき場面

  • 関数内でオブジェクトや配列の状態を変更したい場合:参照渡しを使うことで、関数内で引数のオブジェクトや配列のプロパティを変更すると、元の変数にもその変更が反映されるため、コードの可読性が向上します。

  • 複数の関数で同じオブジェクトや配列を扱いたい場合:参照渡しを使うことで、複数の関数で同じオブジェクトや配列を扱うことができます。これにより、コードの保守性や再利用性が向上します。


まとめ

本記事では、JavaScriptにおける値渡しと参照渡し、そしてstructuredClone()について解説しました。

値渡しと参照渡しの違いを理解することは、バグの解消やパフォーマンスの向上に繋がります。 また、structuredClone()を使うことで、オブジェクトの深いコピーを簡単に実現することができます。これらの知識を習得し、適切に利用することで、より効率的なプログラミングを実現しましょう!

参考文

リクルート情報

  • 弊社ではAWSを中心とした開発を行っています。
  • 開発言語はJavaScript以外に案件によりさまざまですが、一緒に楽しく技術力を磨きませんか?

www.serverworks.co.jp