このロケールの翻訳が存在しないため、英語バージョンのコンテンツを表示しています。 Help us translate this article!
EventTarget
の addEventListener()
メソッドは、特定のイベントが対象に配信されるたびに呼び出される関数を設定します。 対象としてよくあるものは Element
, Document
, Window
ですが、イベントに対応したあらゆるオブジェクトが対象になることができます (XMLHttpRequest
など)。
addEventListener()
は関数または EventListener
を実装したオブジェクトを、呼び出される EventTarget
における指定されたイベント種別のイベントリスナーのリストに加えることで動作します。
構文
target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
target.addEventListener(type, listener[, useCapture, wantsUntrusted ]); // Gecko/Mozilla のみ
引数
type
- 対象とするイベントの種類を表す文字列
listener
- 指定された型のイベントが発生するときに通知 (
Event
インターフェースに準拠しているオブジェクト) を受け取るオブジェクト。これは、EventListener
インタフェースを実装するオブジェクト、あるいは、単純に、JavaScript の関数でなければなりません。コールバックについて詳しくは、イベントリスナーのコールバックを参照してください。 options
Optional- 対象のイベントリスナーの特性を指定する、オプションのオブジェクトです。次のオプションが使用できます。
capture
:Boolean
値で、この型のイベントが DOM ツリーで下に位置するEventTarget
に発送される前に、登録されたlistener
に発送されることを示します。once
:Boolean
値で、listener
の呼び出しを一回のみのとしたいかどうかを値で指定します。true
を指定すると、listener
は一度実行された時に自動的に削除されます。passive
:Boolean
値で、true
ならば、listener
で指定された関数がpreventDefault()
を呼び出さないことを示します。呼び出されたリスナーがpreventDefault()
を呼び出すと、ユーザーエージェントは何もせず、コンソールに警告を出力します。詳細はパッシブリスナーによるスクロール性能の改善をご覧ください。-
mozsystemgroup
:Boolean
値で、リスナーをシステムグループに追加するべきであることを示します。コードが XBL または Firefox ブラウザーの chrome で実行されている場合のみ利用できます。
useCapture
OptionalBoolean
値で、この型のイベントが DOM ツリーの下のEventTarget
に発送される前に、登録されたlistener
に発送されることを示します。ツリーを上方向にバブリングするイベントは、キャプチャを使用するように指定されたリスナーを起動しません。イベント伝播モードは、要素がイベントを受信する順序を決定します。詳細については、 DOM Level 3 Events および JavaScript Event order を参照してください。省略した場合、useCapture
はfalse
となります。-
メモ: イベントターゲットに登録されたイベントリスナーは、補足フェーズや浮上フェーズではなく、ターゲットフェーズのイベントになります。ターゲットフェーズのイベントは、
useCapture
パラメーターにかかわらず、すべてのリスナーを追加された順序で実行します。メモ:useCapture
はどんなブラウザでもオプションになっているわけではありません。完全で最大限の互換性を得たいなら、パラメーターを指定するようにしてください。 wantsUntrusted
true
の場合、このリスナーはウェブコンテンツによって発火された合成イベント (カスタムイベント) を受け取ります (chrome ではデフォルトでfalse
ですが、一般のウェブページではtrue
です)。このパラメーターは Gecko でのみ利用可能であり、主にアドオンやブラウザー自身の役に立つものです。特権ページと非特権ページの間のやり取りを参照してください。
返値
undefined
使用方法のメモ
イベントリスナーのコールバック
The event listener can be specified as either a callback function or as an object that implements EventListener
, whose handleEvent()
method serves as the callback function.
The callback function itself has the same parameters and return value as the handleEvent()
method; that is, the callback accepts a single parameter: an object based on Event
describing the event which has occurred, and it returns nothing.
For example, an event handler callback that can be used to handle both fullscreenchange
and fullscreenerror
might look like this:
function eventHandler(event) { if (event.type == fullscreenchange) { /* handle a full screen toggle */ } else /* fullscreenerror */ { /* handle a full screen toggle error */ } }
Safely detecting option support
In older versions of the DOM specification, the third parameter of addEventListener()
was a Boolean value indicating whether or not to use capture. Over time, it became clear that more options were needed. Rather than adding more parameters to the function (complicating things enormously when dealing with optional values), the third parameter was changed to an object which can contain various properties defining the values of options to configure the process of removing the event listener.
Because older browsers (as well as some not-too-old browsers) still assume the third parameter is a Boolean, you need to build your code to handle this scenario intelligently. You can do this by using feature detection for each of the options you're interested in.
For example, if you want to check for the passive
option:
var passiveSupported = false; try { var options = Object.defineProperty({}, "passive", { get: function() { passiveSupported = true; } }); window.addEventListener("test", options, options); window.removeEventListener("test", options, options); } catch(err) { passiveSupported = false; }
This creates an options
object with a getter function for the passive
property; the getter sets a flag, passiveSupported
, to true
if it gets called. That means that if the browser checks the value of the passive
property on the options
object, passiveSupported
will be set to true
; otherwise, it will remain false
. We then call addEventListener()
to set up a fake event handler, specifying those options, so that the options will be checked if the browser recognizes an object as the third parameter. Then, we call removeEventListener()
to clean up after ourselves. (Note that handleEvent()
is ignored on event listeners that aren't called.)
You can check whether any option is supported this way. Just add a getter for that option using code similar to what is shown above.
Then, when you want to create an actual event listener that uses the options in question, you can do something like this:
someElement.addEventListener("mouseup", handleMouseUp, passiveSupported ? { passive: true } : false);
Here we're adding a listener for the mouseup
event on the element someElement
. For the third parameter, if passiveSupported
is true
, we're specifying an options
object with passive
set to true
; otherwise, we know that we need to pass a Boolean, and we pass false
as the value of the useCapture
parameter.
If you'd prefer, you can use a third-party library like Modernizr or Detect It to do this test for you.
You can learn more from the article about EventListenerOptions
from the Web Incubator Community Group.
例
シンプルなリスナーの追加
この例は、要素上でのマウスクリックを監視するための addEventListener()
の使い方を紹介します。
HTML
<table id="outside"> <tr><td id="t1">one</td></tr> <tr><td id="t2">two</td></tr> </table>
JavaScript
// t2 のコンテンツを変更する関数 function modifyText() { var t2 = document.getElementById("t2"); if (t2.firstChild.nodeValue == "three") { t2.firstChild.nodeValue = "two"; } else { t2.firstChild.nodeValue = "three"; } } // イベントリスナーを table に追加 var el = document.getElementById("outside"); el.addEventListener("click", modifyText, false);
このコードの中で、 modifyText()
が addEventListener()
を使用して登録された click
イベントのリスナーです。表の中のどこかをクリックすると、ハンドラーに上がり、 modifyText()
を実行します。
結果
無名関数を使用したイベントリスナー
ここで、無名関数を使用してイベントリスナーに引数を渡す方法を見てみましょう。
HTML
<table id="outside"> <tr><td id="t1">one</td></tr> <tr><td id="t2">two</td></tr> </table>
JavaScript
// t2 のコンテンツを変更する関数 function modifyText(new_text) { var t2 = document.getElementById("t2"); t2.firstChild.nodeValue = new_text; } // イベントリスナーを table に追加する関数 var el = document.getElementById("outside"); el.addEventListener("click", function(){modifyText("four")}, false);
なお、リスナーは実際にイベントに応答する modifyText()
関数に引数を送信することができるコードをカプセル化している無名関数であることに注意してください。
結果
アロー関数を使用したイベントリスナー
この例はアロー関数表記を使用して実装された、簡単なイベントリスナーを紹介しています。
HTML
<table id="outside"> <tr><td id="t1">one</td></tr> <tr><td id="t2">two</td></tr> </table>
JavaScript
// t2 の中身を変更するための関数 function modifyText(new_text) { var t2 = document.getElementById("t2"); t2.firstChild.nodeValue = new_text; } // アロー関数で table にイベントリスナーを追加 var el = document.getElementById("outside"); el.addEventListener("click", () => { modifyText("four"); }, false);
結果
なお、無名関数とアロー関数は似ており、違いは this
のバインドです。無名関数 (及び伝統的なすべての JavaScript 関数) は自身の this
を作成するのに対し、アロー関数はそれを含む関数の this
を継承します。
つまり、アロー関数を使用したときは、それを含む関数の変数や定数をイベントハンドラーで利用することができます。
Example of options usage
HTML
<div class="outer"> outer, once & none-once <div class="middle" target="_blank"> middle, capture & none-capture <a class="inner1" href="https://www.mozilla.org" target="_blank"> inner1, passive & preventDefault(which is not allowed) </a> <a class="inner2" href="https://developer.mozilla.org/" target="_blank"> inner2, none-passive & preventDefault(not open new page) </a> </div> </div>
CSS
.outer, .middle, .inner1, .inner2 { display:block; width:520px; padding:15px; margin:15px; text-decoration:none; } .outer{ border:1px solid red; color:red; } .middle{ border:1px solid green; color:green; width:460px; } .inner1, .inner2{ border:1px solid purple; color:purple; width:400px; }
JavaScript
let outer = document.getElementsByClassName('outer') [0]; let middle = document.getElementsByClassName('middle')[0]; let inner1 = document.getElementsByClassName('inner1')[0]; let inner2 = document.getElementsByClassName('inner2')[0]; let capture = { capture : true }; let noneCapture = { capture : false }; let once = { once : true }; let noneOnce = { once : false }; let passive = { passive : true }; let nonePassive = { passive : false }; outer .addEventListener('click', onceHandler, once); outer .addEventListener('click', noneOnceHandler, noneOnce); middle.addEventListener('click', captureHandler, capture); middle.addEventListener('click', noneCaptureHandler, noneCapture); inner1.addEventListener('click', passiveHandler, passive); inner2.addEventListener('click', nonePassiveHandler, nonePassive); function onceHandler(event) { alert('outer, once'); } function noneOnceHandler(event) { alert('outer, none-once, default'); } function captureHandler(event) { //event.stopImmediatePropagation(); alert('middle, capture'); } function noneCaptureHandler(event) { alert('middle, none-capture, default'); } function passiveHandler(event) { // Unable to preventDefault inside passive event listener invocation. event.preventDefault(); alert('inner1, passive, open new page'); } function nonePassiveHandler(event) { event.preventDefault(); //event.stopPropagation(); alert('inner2, none-passive, default, not open new page'); }
Result
Click the outer, middle, inner containers respectively to see how the options work.
Before using a particular value in the options
object, it's a good idea to ensure that the user's browser supports it, since these are an addition that not all browsers have supported historically. See Safely detecting option support for details.
メモ
なぜ addEventListener
を使うのか
addEventListener()
は、 W3C DOM で仕様化されている、イベントリスナーを登録するための方法です。その利点は以下の通りです。
- イベントに複数のハンドラーを追加することができます。これは、特に、他のライブラリ/拡張で利用しても上手く動作する必要がある AJAX ライブラリや JavaScript モジュール、その他のライブラリや拡張機能と共に動作させる必要があるコードに役立ちます。
- リスナーがアクティブ化されたときに、その動きを細かくコントロールすることを可能にします(キャプチャリング 対 バブリング)。
- HTML 要素だけでなく、任意の DOM 要素 で動作します。
別の方法である、イベントリスナーを登録するための古い方法 は、後で説明します。
イベント発送中のリスナーの追加
EventListener
がイベント処理中に EventTarget
に追加された場合、それが現在のアクションによって実行されることはありませんが、浮上フェーズのように、後の段階のイベントフローで実行されるかもしれません。
複数の同一のイベントリスナー
複数の同一の EventListener
が、同じ EventTarget
に同じ引数で登録された場合、重複するインスタンスは反映されません。 EventListener
が2回呼び出されることはなく、重複するインスタンスは反映されないので、 removeEventListener()
で手動で削除する必要はありません。
ハンドラー内での this
の値
一連の類似した要素に対して一般的なハンドラーを使いたい場合のように、イベントハンドラーが実行される要素を参照したいということがたびたびあります。
addEventListener()
を使って要素にハンドラー関数を設定したとき、ハンドラーの中の this
の値は要素への参照となります。これはハンドラーに渡された event 引数の currentTarget プロパティの値と同じです。
onclick
のようなイベントハンドラーが HTML 要素に指定されていた場合、イベント属性の Javascirpt コードの値は、事実上 addEventListener()
を使用するような方法で this
の値をバインドするハンドラー関数に置き換えられます。つまり、コード内に直接 this
が現れた場合には、要素への参照に置き換えられます。けれど、属性の値のコードによって呼ばれた先の関数の内側では、this
の値はふつうのルールに従って決まることに注意してください。したがって、以下のような場合:
<table id="t" onclick="modifyText();"> . . .
onclick イベントで呼び出されたときの modifyText()
内の this
の値は、グローバルオブジェクトWindow
への参照となります。 (もしくは strict mode の場合、undefined
になります。)
bind()
を使用した this
の指定
Function.prototype.bind()
メソッドで、その関数のすべての呼び出しにおいて this
として使用される値を指定できます。これを使えば、関数がどこから呼び出されるかによって this
の値が変わってしまうというややこしい問題を簡単に回避できます。ただし、リスナーを後で削除できるように、そのリスナーへの参照を残しておく必要があります。
以下は bind()
を使った場合と使わない場合の例です。
var Something = function(element) { // |this| is a newly created object this.name = 'Something Good'; this.onclick1 = function(event) { console.log(this.name); // this は element なので undefined になります }; this.onclick2 = function(event) { console.log(this.name); // this はバインドされた Something オブジェクトなので「Something Good」と出力されます }; element.addEventListener('click', this.onclick1, false); element.addEventListener('click', this.onclick2.bind(this), false); // これが仕掛けです } var s = new Something(document.body);
上の例の問題は、 bind()
の付いたリスナーを削除できないということです。もうひとつの解決策は、あらゆるイベントを捕捉する handleEvent()
という特別な関数を使用することです。
var Something = function(element) { // |this| is a newly created object this.name = 'Something Good'; this.handleEvent = function(event) { console.log(this.name); // this は Something オブジェクトなので「Something Good」と出力されます switch(event.type) { case 'click': // 処理 break; case 'dblclick': // 処理 break; } }; // この場合のリスナーは this であって this.handleEvent でないことに注意してください element.addEventListener('click', this, false); element.addEventListener('dblclick', this, false); // リスナーは適切に削除できます element.removeEventListener('click', this, false); element.removeEventListener('dblclick', this, false); } var s = new Something(document.body);
this の参照を扱うためのもう一つの方法は、 EventListener
にアクセスする必要のあるフィールドを含むオブジェクトのメソッドを呼び出す関数を渡すことです。
class SomeClass { constructor() { this.name = 'Something Good'; } register() { var that = this; window.addEventListener('keydown', function(e) {return that.someMethod(e);}); } someMethod(e) { console.log(this.name); switch(e.keyCode) { case 5: // some code here... break; case 6: // some code here... break; } } } var myObject = new SomeClass(); myObject.register();
古い Internet Explorer と attachEvent
IE9 より前の Internet Explorer では、標準の addEventListener
ではなく、 attachEvent()
を使わなければなりません。 IE に対応するためには、上記の例を以下のように修正しなけれなりません。
if (el.addEventListener) { el.addEventListener('click', modifyText, false); } else if (el.attachEvent) { el.attachEvent('onclick', modifyText); }
attachEvent()
の欠点が 1 つあります。 this
の値がイベントを起こした要素ではなく、 window
オブジェクトへの参照になってしまうことです。
The attachEvent()
method could be paired with the onresize
event to detect when certain elements in a webpage were resized. The proprietary mselementresize
event, when paired with the addEventListener
method of registering event handlers, provides similar functionality as onresize
, firing when certain HTML elements are resized.
互換性
次のコードをスクリプトの初めに書いておくと、 Internet Explorer 8 では対応していない addEventListener
, removeEventListener
, Event.preventDefault()
, Event.stopPropagation()
が動作するようになります。このコードは、 handleEvent()
と DOMContentLoaded
イベントにも対応します。
メモ: useCapture
に対応していないため、 IE 8 では代わりの方法はありません。以下のコードは IE 8 への対応を追加するだけです。また、 IE 8 用の代替モジュールは、標準モードのみで動作します。 doctype 宣言が必要です。
(function() { if (!Event.prototype.preventDefault) { Event.prototype.preventDefault=function() { this.returnValue=false; }; } if (!Event.prototype.stopPropagation) { Event.prototype.stopPropagation=function() { this.cancelBubble=true; }; } if (!Element.prototype.addEventListener) { var eventListeners=[]; var addEventListener=function(type,listener /*, useCapture (will be ignored) */) { var self=this; var wrapper=function(e) { e.target=e.srcElement; e.currentTarget=self; if (typeof listener.handleEvent != 'undefined') { listener.handleEvent(e); } else { listener.call(self,e); } }; if (type=="DOMContentLoaded") { var wrapper2=function(e) { if (document.readyState=="complete") { wrapper(e); } }; document.attachEvent("onreadystatechange",wrapper2); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2}); if (document.readyState=="complete") { var e=new Event(); e.srcElement=window; wrapper2(e); } } else { this.attachEvent("on"+type,wrapper); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper}); } }; var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) { var counter=0; while (counter<eventListeners.length) { var eventListener=eventListeners[counter]; if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) { if (type=="DOMContentLoaded") { this.detachEvent("onreadystatechange",eventListener.wrapper); } else { this.detachEvent("on"+type,eventListener.wrapper); } eventListeners.splice(counter, 1); break; } ++counter; } }; Element.prototype.addEventListener=addEventListener; Element.prototype.removeEventListener=removeEventListener; if (HTMLDocument) { HTMLDocument.prototype.addEventListener=addEventListener; HTMLDocument.prototype.removeEventListener=removeEventListener; } if (Window) { Window.prototype.addEventListener=addEventListener; Window.prototype.removeEventListener=removeEventListener; } } })();
イベントリスナーを登録するための古い方法
addEventListener()
は、DOM 2 Events 仕様で導入されました。それ以前は、以下のようにイベントリスナーを登録していました。
// 関数へのリファレンスを利用する方法—'()' が無いことに注意してください el.onclick = modifyText; // 関数式を利用する方法 element.onclick = function() { /* ...文... */ };
このメソッドは、要素上に click
イベントリスナーが既に存在する場合、置き換えてしまいます。 他のイベント、blur
(onblur
)、keypress
(onkeypress
)、などのような関連するイベントハンドラも同様です。
これは本質的には DOM 0 の一部分なので、この方法は、非常に広くサポートされており、特別なクロスブラウザ用のコードも必要ありません。それ故、addEventListener()
の独自の機能が必要でない場合に、動的にイベントリスナーを登録する方法として普通に使われています。
メモリに関する問題
var i; var els = document.getElementsByTagName('*'); // ケース 1 for(i=0 ; i<els.length ; i++){ els[i].addEventListener("click", function(e){/*関数の処理*/}, false); } // ケース 2 function processEvent(e){ /*関数の処理*/ } for(i=0 ; i<els.length ; i++){ els[i].addEventListener("click", processEvent, false); }
最初の例では、新しい匿名関数がループごとに作られています。これに対して 2 番目の例では、前に宣言された同じ関数がイベントハンドラとして使われています。そのため、メモリの消費が抑えられます。その上、最初の例では匿名関数への参照が保存されておらず、ハンドラーへの参照がないため、 removeEventListener()
を実行することが不可能になってしまっています。一方、2番目の例では、 myElement.removeEventListener("click", processEvent, false)
とすることができます。
パッシブリスナーを用いたスクロールの性能改善
According to the specification, the default value for the passive
option is always false. However, this introduces the potential for event listeners handling certain touch events (among others) to block the browser's main thread while it is attempting to handle scrolling, resulting in possibly enormous reduction in performance during scroll handling.
To prevent this problem, some browsers (specifically, Chrome and Firefox) have changed the default value of the passive
option to true
for the touchstart
and touchmove
events on the document-level nodes Window
, Document
, and Document.body
. This prevents the event listener from being called, so it can't block page rendering while the user is scrolling.
Note: See the compatibility table below if you need to know which browsers (and/or which versions of those browsers) implement this altered behavior.
You can override this behavior by explicitly setting the value of passive
to false
, as shown here:
/* Feature detection */
var passiveSupported = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, "passive", { get: function() { passiveSupported = true; } }));
} catch(err) {}
/* リスナーを登録 */
var elem = document.getElementById('elem');
elem.addEventListener('touchmove
', function listener() {
/* do something */
}, passiveSupported ? { passive: false } : false);
On older browsers that don't support the options
parameter to addEventListener()
, attempting to use it prevents the use of the useCapture
argument without proper use of feature detection.
You don't need to worry about the value of passive
for the basic scroll
event. Since it can't be canceled, event listeners can't block page rendering anyway.
仕様書
ブラウザーの対応
デスクトップ | モバイル | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
addEventListener | Chrome
完全対応
1
| Edge 完全対応 12 | Firefox 完全対応 1 | IE
完全対応
9
| Opera 完全対応 7 | Safari 完全対応 1 | WebView Android
完全対応
1
| Chrome Android
完全対応
18
| Firefox Android 完全対応 4 | Opera Android 完全対応 10.1 | Safari iOS 完全対応 1 | Samsung Internet Android 完全対応 あり |
useCapture parameter made optional | Chrome 完全対応 1 | Edge 完全対応 あり | Firefox 完全対応 6 | IE 完全対応 9 | Opera 完全対応 11.6 | Safari 完全対応 あり | WebView Android 完全対応 1 | Chrome Android 完全対応 18 | Firefox Android 完全対応 6 | Opera Android 完全対応 12 | Safari iOS 完全対応 あり | Samsung Internet Android 完全対応 あり |
Form with options object supported (third parameter can be either options or a Boolean , for backwards compatibility) | Chrome 完全対応 49 | Edge 完全対応 あり | Firefox 完全対応 49 | IE 未対応 なし | Opera 完全対応 あり | Safari 完全対応 10 | WebView Android 完全対応 49 | Chrome Android 完全対応 49 | Firefox Android 完全対応 49 | Opera Android 完全対応 あり | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 5.0 |
options : capture option | Chrome 完全対応 52 | Edge 完全対応 あり | Firefox 完全対応 あり | IE 未対応 なし | Opera 完全対応 あり | Safari 完全対応 あり | WebView Android 完全対応 52 | Chrome Android 完全対応 52 | Firefox Android 完全対応 あり | Opera Android 完全対応 あり | Safari iOS 完全対応 あり | Samsung Internet Android 完全対応 6.0 |
options : once option | Chrome 完全対応 55 | Edge 完全対応 あり | Firefox 完全対応 50 | IE 未対応 なし | Opera 完全対応 42 | Safari 完全対応 あり | WebView Android 完全対応 55 | Chrome Android 完全対応 55 | Firefox Android 完全対応 50 | Opera Android 完全対応 42 | Safari iOS 完全対応 あり | Samsung Internet Android 完全対応 6.0 |
options : passive option | Chrome 完全対応 51 | Edge 完全対応 あり | Firefox 完全対応 あり | IE 未対応 なし | Opera 完全対応 あり | Safari 完全対応 あり | WebView Android 完全対応 51 | Chrome Android 完全対応 51 | Firefox Android 完全対応 あり | Opera Android 完全対応 あり | Safari iOS 完全対応 あり | Samsung Internet Android 完全対応 5.0 |
options : passive option defaults to true for touchstart and touchmove events | Chrome 完全対応 55 | Edge 未対応 なし | Firefox 完全対応 61 | IE 未対応 なし | Opera ? | Safari 未対応 なし | WebView Android 完全対応 55 | Chrome Android 完全対応 55 | Firefox Android 完全対応 61 | Opera Android ? | Safari iOS 未対応 なし | Samsung Internet Android 完全対応 6.0 |
options : passive option defaults to true for wheel and mousewheel events | Chrome 完全対応 73 | Edge 未対応 なし | Firefox ? | IE 未対応 なし | Opera ? | Safari 未対応 なし | WebView Android 完全対応 73 | Chrome Android 完全対応 73 | Firefox Android ? | Opera Android ? | Safari iOS 未対応 なし | Samsung Internet Android ? |
凡例
- 完全対応
- 完全対応
- 未対応
- 未対応
- 実装状況不明
- 実装状況不明
- 実装ノートを参照してください。
- 実装ノートを参照してください。
- 非標準の名前を使用しています。
- 非標準の名前を使用しています。