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

JavaScriptにおける循環参照とは?実例と設計上の注意点を解説

循環参照とは?

循環参照(サイクリックリファレンス)とは、2つの独立したオブジェクトが互いに相手への参照を持ち合う状態を指します。

メモリリーク問題は過去のものに

古いブラウザでは、この循環参照がメモリリークの原因となることがありました。しかし、現代のガベージコレクション(GC)アルゴリズムはマーク&スイープ方式などを採用しており、循環する依存関係でも正しく検出して解放できるようになったため、現在ではこれは問題ではなくなっています。

設計の観点から見た循環参照

ただし、純粋なソフトウェア設計の観点から言えば、循環参照は依然として避けるべき「コードの不吉な臭い(code smell)」です。互いに参照し合う2つのオブジェクトは密結合(tight coupling)の状態にあり、片方のオブジェクトに変更を加えると、もう片方にも修正が必要になる可能性が高くなります。

具体例:Dog と Person

例として、「犬(Dog)」と「人(Person)」という2つのオブジェクトを考えてみましょう。犬オブジェクトだけで飼い主を参照でき、同時に人オブジェクトからもペットを参照できるようにしたい、というケースです。

let dog = new Dog();
let person = new Person();
// 循環参照を作成
dog.owner = person;
person.pet = dog;

このように dog.ownerperson.pet が互いを指し合うことで、循環参照が発生します。

循環参照への対処方法

多くの場面では、実際にアクセスが必要なのは片方のオブジェクトだけであり、もう片方はそこから導出できます。その場合は、リンクの片方を断ち切るだけで循環を解消できます。

どうしても双方向の参照が必要な場合は、Map を使って逆方向の対応関係を別途管理する手法もあります。ただし、そのような回避策(hack)を積み重ねるよりも、状況によっては循環参照をそのまま許容する方がシンプルで保守しやすいこともあります。大切なのは、密結合による影響範囲を理解した上で、設計として適切な判断を下すことです。

  1. JavaScriptのunescape()関数とは?使い方とサンプルコードをわかりやすく解説

    JavaScriptのunescape()関数は、escape()関数によってエンコードされた文字列をデコード(元に戻す)ための関数です。ただし、この関数はECMAScript v3以降で非推奨(deprecated)とされており、現在では代わりにdecodeURI()やdecodeURIComponent()を使用することが推奨されています。レガシーなコードの理解や保守の際に役立つ知識なので、ここで基本的な動作を確認しておきましょう。unescape()関数の基本的な使い方以下のコードは、unescape()関数を使ってエンコードされたURL文字列をデコードする例です。ボタンをクリックすると

  2. JavaScriptにおける継承の基本を具体例で解説

    JavaScriptは、クラスベースではなくプロトタイプベースのオブジェクト指向言語です。そのため、継承はprototype(プロトタイプ)オブジェクトを通じて実現されます。コンストラクタ関数のprototypeプロパティにメソッドやプロパティを追加すると、そのコンストラクタから生成されたすべてのインスタンスが、それらを共有して利用できるようになります。 プロトタイプによる継承の仕組み JavaScriptでは、インスタンスからプロパティやメソッドが参照されるとき、まずオブジェクト自身を検索し、見つからなければプロトタイプチェーンをたどって上位のオブジェクトへと探しに行きます。これにより、各イ