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

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

新規登録して質問してみよう
ただいま回答率
85.50%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

Q&A

解決済

1回答

10260閲覧

生成したインスタンスを削除したい

mintia191

総合スコア3

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

0グッド

0クリップ

投稿2020/05/29 06:17

前提・実現したいこと

javaScriptで数字の書かれたパネル(li要素)を順番にクリックするゲームを作っています。
select要素でレベルを選択すると、現在表示されているパネルをいったん削除し、新しくレベルに応じたパネルを生成したい。

発生している問題・エラーメッセージ

レベルを変更すると、現在表示されているパネルが削除されず、パネルが追加される。 (例)レベル2からレベル3に変更すると、(2のパネル数)+(3のパネル数)が表示される

該当のソースコード

javascript

1'use strict'; 2 3{ 4 class Panel { 5 constructor(game) { 6 this.game = game; 7 this.el = document.createElement('li'); 8 this.el.classList.add('pressed'); 9 this.el.addEventListener('click', () => { 10 this.check(); 11 }); 12 } 13 14 getEl() { 15 return this.el; 16 } 17 18 activate(num) { 19 this.el.classList.remove('pressed'); 20 this.el.textContent = num; 21 } 22 23 check() { 24 if (this.game.getCurrentNum() === parseInt(this.el.textContent, 10)) { 25 this.el.classList.add('pressed'); 26 this.game.addCurrentNum(); 27 if (this.game.getCurrentNum() === this.game.getLevel() ** 2) { 28 clearTimeout(this.game.getTimeoutId()); 29 } 30 } 31 } 32 } 33 34 class Board { 35 constructor(game) { 36 this.game = game; 37 this.panels = []; 38 for (let i = 0; i < this.game.getLevel() ** 2; i++) { 39 this.panels.push(new Panel(this.game)); 40 } 41 this.setup(); 42 } 43 44 setup() { 45 const board = document.getElementById('board'); 46 this.panels.forEach(panel => { 47 board.appendChild(panel.getEl()); 48 }); 49 } 50 51 activate() { 52 const nums = []; 53 for (let i = 0; i < this.game.getLevel() ** 2; i++) { 54 nums.push(i); 55 } 56 57 this.panels.forEach(panel => { 58 const num = nums.splice(Math.floor(Math.random() * nums.length), 1)[0]; 59 panel.activate(num); 60 }); 61 } 62 } 63 64 class Game { 65 constructor(level) { 66 this.level = level; 67 this.board = new Board(this); 68 69 this.currentNum = undefined; 70 this.startTime = undefined; 71 this.timeoutId = undefined; 72 73 this.getLevel(); 74 75 const btn = document.getElementById('btn'); 76 btn.addEventListener('click', () => { 77 this.start(); 78 }); 79 this.setup(); 80 } 81 82 setup() { 83 const container = document.getElementById('container'); 84 const PANEL_WIDTH = 50; 85 const BOARD_PADDING = 10; 86 /* 50px * 2 + 10px * 2 */ 87 container.style.width = PANEL_WIDTH * this.level + BOARD_PADDING * 2 + 'px'; 88 } 89 90 start() { 91 if (typeof this.timeoutId !== 'undefined') { 92 clearTimeout(this.timeoutId); 93 } 94 95 this.currentNum = 0; 96 this.board.activate(); 97 98 this.startTime = Date.now(); 99 this.runTimer(); 100 } 101 102 runTimer() { 103 const timer = document.getElementById('timer'); 104 timer.textContent = ((Date.now() - this.startTime) / 1000).toFixed(2); 105 106 this.timeoutId = setTimeout(() => { 107 this.runTimer(); 108 }, 10); 109 } 110 111 addCurrentNum() { 112 this.currentNum++; 113 } 114 115 getCurrentNum() { 116 return this.currentNum; 117 } 118 119 getTimeoutId() { 120 return this.timeoutId; 121 } 122 123 getLevel() { 124 return this.level; 125 } 126 127 128 } 129 130 131 // 最初に表示される 132 new Game(2); 133 134 // selectから要素を取得し新たにパネルを生成 135 const level = document.getElementById('level'); 136 level.addEventListener('change', () => { 137 new Game(level.value); 138 }); 139 140}

試したこと

changeイベントの最初に、new Game(0);やnew Game(undefined);を挿入(何も変わらず)
同じ個所に、new Panel();にも同様の引数を入れて書いたが機能せず。

補足情報(FW/ツールのバージョンなど)

初心者なためわかりずらくてすみません。
ブラウザ chrome
エディター VSCode
フレームワーク 未使用

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

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

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

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

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

guest

回答1

0

ベストアンサー

生成したインスタンスを削除したい

インスタンスの削除は インスタンスを格納する変数など(配列要素やオブジェクトの属性値)に null を与えてガベージコレクタ が専有していたメモリ領域を開放するように実装にします。
変数等に新しいインスタンスを代入する方法もあります。
配列であれば、shift()pop()、添字指定で上書き、ary.length = 0 などもインスタンスの削除(メモリ開放)手段となります。

ご質問のコードにある、new 演算子でインスタンス生成する場合、必ず変数を用意するなど、インスタンスの管理が重要になります。

レベルを変更すると、現在表示されているパネルが削除されず、パネルが追加される。

appendChild() がインスタンスを文書木上に保持する処理なので、removeChild() を使って明示的に削除してください。

Board クラス で panels プロパティまで設定して管理しているにもかかわらず、単純に push する実装だからでしょう。

index 指定して明示的に上書きするとともに、document のツリーにある内容も明示的に削除する必要があるのではないでしょうか。

投稿2020/05/29 07:56

編集2020/05/29 07:58
AkitoshiManabe

総合スコア5432

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

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

mintia191

2020/05/29 12:37

ご返答ありがとうございます。 removeChild()を使って、Board クラスのsetup()に以下を挿入し、パネルを削除し追加することができました。 while (board.firstChild) { board.removeChild(board.firstChild); } ですが、PanelクラスのclearTimeoutが機能せず、タイマーが止まらなくなってしまいました。 教えてくださったことをいろいろ試行錯誤したのですが、どうやってもうまくいきません。 もしよろしければ、少し具体的に教えていただくことはできないでしょうか。 よろしくお願い致します。
AkitoshiManabe

2020/05/29 20:36

> 少し具体的に教えていただくことはできないでしょうか clearTimeout() の前にインスタンスを削除したのが原因だとは思いますが、 再現できる内容ではありませんでしたので、具体的に答えるのは無理です。 本題「生成したインスタンスを削除」には回答したつもりです。
mintia191

2020/05/30 01:14

仰る通りです。 申し訳ございませんでした。 ご返答頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問