⊗jsPmTrTCL 451 of 505 menu

JavaScriptにおけるタイマーとコンテキストの喪失

イベントハンドラー内でタイマーを使用する際には、 コンテキスト喪失の問題が待ち構えています。 例を見てみましょう。

次のような入力フィールドがあるとします:

<input id="elem" value="text">

この入力フィールドをクリックした際に匿名関数が実行され、 その関数内でタイマーが起動し、毎秒何かをコンソールに 出力するようにしましょう:

let elem = document.querySelector('#elem'); elem.addEventListener('click', function() { setInterval(function() { console.log('!!!'); // コンソールに何かを出力 }, 1000); });

ここまでは正常に動作します。しかし、今度はコンソールに 入力フィールドの value を出力したいとすると、 驚きが待っています:コンソールには undefined が出力されます:

elem.addEventListener('click', function() { setInterval(function() { console.log(this.value); // undefinedが出力される }, 1000); });

問題は、関数内関数ができてしまうことです。 クリック時に呼び出される外側の匿名関数と、 タイマーによって起動される内側の匿名関数があります。 外側の関数では this は入力フィールドを指しますが、 内側の関数ではそうではありません。コンテキストの喪失が 発生しています。

なぜ、以前のレッスンで起こったようにコンソールエラーに ならないで undefined が出力されるのでしょうか? それは、setInterval 経由で呼び出される関数内の thiswindow を指すためです。

つまり、window オブジェクトから value プロパティを 読み取ろうとしているのです。このように:window.value。 window オブジェクトにはそのようなプロパティは存在しないため、 (エラーではなく)undefined を得るのです。

self を導入してこの問題を修正しましょう:

elem.addEventListener('click', function() { let self = this; setInterval(function() { console.log(self.value); }, 1000); });

次のようなコードがあるとします:

<input type="button" id="elem" value="1"> let elem = document.querySelector('#elem'); elem.addEventListener('click', function() { setInterval(function() { this.value = Number(elem.value) + 1; }, 1000); });

このコードの作者は、ボタンが押されると、 そのボタンの値が毎秒 1 ずつ増加することを 期待していました。しかし、ボタンを押しても 何も起こりません。作者のコードの誤りを修正し、 なぜそのエラーが発生したのかを作者に説明する 文章を書いてください。

日本語
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItalianoქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
当サイトでは、サイトの動作、分析、パーソナライゼーションのためにクッキーを使用しています。 データ処理はプライバシーポリシーに従って行われます。
すべて受け入れる 設定 拒否