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

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

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

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

Q&A

解決済

3回答

2139閲覧

Javascript : thisの実体について

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

3クリップ

投稿2016/08/12 13:07

html

1<input type="range" name="count" min="0" max="20" value="8" id="count">

javascript

1const count = document.getElementById("count"); 2 3count.addEventListener('change', () => { 4 console.log(this.count.value); 5});

Javascript初心者です。フォームの値を取得して、フロントエンドでのバリデーションの練習をしたいと思っています。addEventListener内でのthisの実体はcountだと思っていたのですが、console.log(this)をしてみるとWindow index.htmlであることがわかり、上記のようにthis.count.valueとすることで想定通りの結果を得ることができました。
constをした時点でdocument.としているので、addEventListener内でもthisの実体がcountとならないのはなんとなく理解できたのですが、どうも直感的でない気がします。質問したいことは、なんらかコードを変えることによって、thisの実体がcountを指すようにし、以下のようなコードで想定通りの結果を得ることができるかどうかをお聞きしたいです。

javascript

1const count = document.getElementById("count"); 2 3count.addEventListener('change', () => { 4 console.log(this.value); 5});

質問がわかりにくいかもしれませんが、よろしくお願い致します。

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

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

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

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

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

guest

回答3

0

ベストアンサー

アロー関数を使用した場合、thisの指すものが変数と同様に、最も近い上位のthisスコープを指すようになります。

質問に使用したコードでは、addEventListenerにアロー関数を渡しています。そのためアロー関数内部の指すthisはひとつ上のスコープのthis(=グローバルオブジェクト、ブラウザにおいてはwindowオブジェクト)を指すようになります。

以下の様にアロー関数を使用せず、通常の関数を使用してaddEventListenerに登録した場合、(bind等でthisが束縛されていなければ)thisは対象となる要素を指すようになります。

const count = document.getElementById("count"); console.log(this); // グローバルにあるthisはwindowを指す count.addEventListener('change', ()=> { console.log(this); // これはアロー関数なので一つ上位のスコープ、つまりはグローバルのthisを指す }); count.addEventListener('change', function(){ console.log(this); // これは通常の関数なので呼び出し時に決定される。addEventListenerの場合は対象となるcount Element }); count.addEventListener('change', function(){ console.log(this); // これは通常の関数に対してbindでthis指定しているため、thisはbindで束縛された文字列 "gao" になる。 // (※ただしapply/bind/call の性質上、thisに入るのはそれをnew Stringでラップしたラッパーオブジェクト) }.bind("gao"));

また、addEventListenerに登録するコールバック関数の第一引数には、currentTargetというプロパティが存在しており、これが通常関数におけるthisと等価のものを指します。
アロー関数を用いて記述する場合は、こちらを利用して参照することも出来ますので合わせて知っておくと便利です。

const count = document.getElementById("count"); count.addEventListener('change', (eve)=> { console.log(eve.currentTarget); // これはcount Element を指す });

投稿2016/08/12 13:23

gaogao_9

総合スコア103

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

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

退会済みユーザー

退会済みユーザー

2016/08/12 13:31

わかりやすい回答をありがとうございます。解決策としては様々なものがあるということがわかりました。さらに質問なのですが、実際の現場ではどの方法が一般的に用いられるのでしょうか。
gaogao_9

2016/08/12 13:55 編集

ケースバイケースですね。 アロー関数を用いて記述した場合、以下の様なパターンにおいてはシンプルに記述することが出来るようになります。 1. 発火したコールバック関数内部において上位スコープのthisを参照したいケース 2. 発火したコールバック関数内部において、currentTargetを使用しなくてもよいケース 一方で、以下の様なパターンにおいてはかえって冗長になりうるケースが存在します。 1. 一度登録したイベントをremoveEventListenerで解除しうるケース (※最新の仕様では第三引数にonce: trueを指定することにより1度だけ発火するイベントをシンプルに記述できることが提案されている(実装されている処理系があるかは知らない)ため、場合によってはアロー関数が有利になり得る) 2. bind等でthisの値を束縛したいケース(アロー関数にbindでthis束縛することは出来ない) このため、どちらが良いかというのは一概に決定しづらく、現場ごとでどちらを採用するかは変わってくると思います。両者が混在する事もありえるでしょう。 ---- また、そもそもアロー関数自体がES2015で追加された、比較的新しい構文なので、IEを代表とする古いブラウザでは動作しないという問題があります。 一方で、古いブラウザを相手にしなくても良い場合には、気にせずアロー関数を利用できますので、アロー関数を用いて記述しても問題無いでしょう。 因みにES2015仕様に基づいて記述されたコードをES5(IE9以降でも動く仕様)に落としこむものとして、babelと呼ばれる有名なプロジェクトがあります。 こちらを利用できる場合はbabelを利用して古いブラウザへの対応することも出来ます。 (babel javascript 辺りでググったら色々情報出てくると思います。)
退会済みユーザー

退会済みユーザー

2016/08/12 14:03

ありがとうございます。勉強を始めたばかりなので、今後はES2015の構文を積極的に使い、ES5までの構文も可能な限り同時に学ぶという方針で勉強していきたいと思います。ベストアンサーとさせていただきます。
guest

0

むしろ、ES6から導入された=>による無名関数には、thisを外側のthisに固定するという意味があります(MDN)。

=>を使わずにfunction()で書けば、thisはイベントの発生したオブジェクトになります。

投稿2016/08/12 13:20

maisumakun

総合スコア145121

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

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

退会済みユーザー

退会済みユーザー

2016/08/12 13:57

回答ありがとうございます。`function()`の省略記法としてES6からはアロー関数が使えるのだと認識していましたが、これは誤った認識だと思って間違いないでしょうか。
maisumakun

2016/08/12 14:39

「thisが変わる」という、状況によってはどうでもいい、逆に状況によっては重要になる違いがあります。
guest

0

javascript

1<script> 2document.addEventListener ('change',function(e){console.log(e.target.id)},true); 3</script>

HTML

1<input type="range" name="count" min="0" max="20" value="8" id="count">

としておけば、別段getElementByIdでオブジェクトをつかむ必要もないです

投稿2016/08/12 13:45

yambejp

総合スコア114572

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

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

退会済みユーザー

退会済みユーザー

2016/08/12 14:04

回答ありがとうございます。これまで知らなかった新たな書き方でした。今後ともよろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問