質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

1回答

1036閲覧

【JavaScript】WeakMapの箇所についてコード例が読み解けず困っています。

manape

総合スコア12

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2021/09/11 07:48

編集2021/09/11 08:08

概要

JavaScript勉強中の初学者です。
JS Primerを読んでいて不明なところがありご質問させていただければと思います。

ご質問箇所

▼該当箇所
https://jsprimer.net/basic/map-and-set/#weakmap

WeakMapについて学んでおり、弱い参照でGCからのメモリ解放を妨げないためにメモリリークを起こさないようにできる、という概要はなんとなく理解できました。

その中で、WeakMapの欄にある使用例の処理について、いまいち何をしているのか、また何を意図してそうなっているのかがソースコードから読み解けず、お知恵をお貸しいただけると幸いです。以下該当の箇所の引用です。

// イベントリスナーを管理するマップ const listenersMap = new WeakMap(); class EventEmitter { addListener(listener) { // this にひもづいたリスナーの配列を取得する const listeners = listenersMap.get(this) ?? []; const newListeners = listeners.concat(listener); // this をキーに新しい配列をセットする listenersMap.set(this, newListeners); } } // 上記クラスの実行例 let eventEmitter = new EventEmitter(); // イベントリスナーを追加する eventEmitter.addListener(() => { console.log("イベントが発火しました"); }); // eventEmitterへの参照がなくなったことで自動的にイベントリスナーが解放される eventEmitter = null;

考えたこととご質問

  1. addListenerメソッドは、あくまでイベント発火時にのみMapを参照できていればよくその他の時はMapへの参照を持っておく必要がないため、メモリを解放するためにわざわざこのような実装にしている?
  2. this (クラスインスタンス) を WeakMap のキーにすることで、インスタンスの外からはアクセスできない値を保持できます。 とJS Primerにはありましたが、そうしなかった場合、どんな問題があり得るのでしょうか?(つまり、インスタンスの外から値がアクセスできてしまう)
  3. 本旨とずれるかもしれませんが、このaddListenerメソッドは結局のところ何をしているのでしょうか?

2の質問のように、インスタンス自身を新たなkeyとしてセットし、今までsetしたイベントリスナーと合体した配列を値にセットしている、ということはわかるのですが、それで一体どんなことが嬉しいのかいまいちイメージできません。イベント発火ごとに発火時の記録を格納していく、みたいなことでしょうか。。

基本的なことが抜け落ちているかもしれず、また例のコードなのでいろいろな想定ができるかとは思うので漠然としたご質問になり恐縮ですが、
宜しくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

弱参照

WeakMap弱参照であり、「keyがどこからも参照されなくなった場合に、WeakMapに格納された key,value はガベージコレクションによって削除」されます。

JavaScript

1const wm = new WeakMap; 2constt obj = {}; 3wm.set(obj, 1); 4obj = null; // 変数 obj に格納されたオブジェクトへの参照を切る 5console.log(wm); // 参照が失われた為、WeakMapに格納された key,value はGCが回収し、削除される

スコープ

  • new WeakMap に格納された値を参照するには「インスタンス」と「key」の両方が必要です。
  • new Map は「インスタンス」のみ参照できれば、Map.prototype.entries で全ての値を参照できます。

EventEmitter の利点

ご質問のコードは WeakMap.prototype.set だけを持つ WeakMap で全ての値を参照できます。
このコードだけでは何のメリットもありません。
前述の「弱参照」と「スコープ」の利点を持っているので、「WeakMap互換オブジェクトを prototype 拡張する目的」で使用することが多いと思います。

private propertyを作ることもできます。

Re: manape さん

投稿2021/09/11 11:50

think49

総合スコア18164

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manape

2021/09/12 06:24

ご回答ありがとうございます。 参考にリンクも貼っていただき、より理解を深めることができました。 この例のコードだけではなんのメリットも無く、ただWeakMap自体は「今までJavaScriptでは実現しづらかったプライベートプロパティを作れるようになる」ことが大きな意義なのだとわかりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問