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

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

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

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

3回答

1234閲覧

JQueryの$(this)のスコープについて

pegy

総合スコア243

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2021/09/29 06:41

編集2021/09/29 06:42

下記のように、複数の要素$('li')を取得してarray.map()を利用する場合、無意識に$(this)を使っていて、ふと怖くなり調べだしました。
alert($(this).text()); //this_1"push"を返し、
alert($(this).text()); //this_2は順番に"1""2""3"を返してくれます。

これ自体は無意識に意図していた動作なのですが、はてthis_2は何故クリックされた$('button')要素のtext()を返さないのかという問題なのですが、恐らく$(this)のスコープの範囲の問題なのかと推察しております。array.map以外についても、一般的ばルールとしてこの$(this)の範囲がJquery上どのように定義されているのかを調べたかったのですが、見つけることができず、もし参照すべきリファレンス等ご存じの方がいらっしゃればお力添え頂けると幸いです。

宜しくお願い申し上げます。

html

1<ul> 2 <li>1</li> 3 <li>2</li> 4 <li>3</li> 5</ul> 6 7<button>push</button>

Javscript

1$('button').on('click',function(){ 2alert($(this).text()); //this_1 3 var get_li = $('li'); 4 get_li.map(function(){ 5 alert($(this).text()); //this_2 6 }) 7})

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

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

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

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

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

guest

回答3

0

jQueryのドキュメントに書いてあります。

on()

When jQuery calls a handler, the this keyword is a reference to the element where the event is being delivered;

map()

Within the callback function, this refers to the current DOM element for each iteration.

jQueryに関数を読んでもらっている限り、thisの内容がjQueryが決めているもの以外になることはありません。(アロー関数や bind()した場合を除く)

投稿2021/09/29 06:54

編集2021/09/29 08:27
int32_t

総合スコア21012

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

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

pegy

2021/09/29 07:12

t自分自身では見つけることができませんでした、ありがとうございます。 ただ、今回のようなケースではon()もmap()も同時に$(this)の参照先が存在しておりそれがネスト化されている状況と思慮します。 この場合には内側のメソッド内で$(this)の特定のrefer先がある場合には、そちらが優先される(今回のケースではmap())が一般的な原則が存在していると理解しても良いのでしょうか? それともメソッドによってはこれが逆転するような可能性があるものなのでしょうか? 常に$(this)の参照先がネスト化されて利用される場合、原則に基づくのかイレギュラーを気にしながら進むべきなのか、整理したいというのが趣旨となります。 宜しくお願い申し上げます。
maisumakun

2021/09/29 07:40 編集

> 常に$(this)の参照先がネスト化されて利用される場合、原則に基づくのかイレギュラーを気にしながら進むべきなのか、整理したいというのが趣旨となります。 そんなに気になるのであればthisは使わず、コールバックの引数を経由して明示的に受け取る方法もあります(アロー関数ではjQueryから渡されるthisを受け取れないので、引数から回収するよりありません)。
int32_t

2021/09/29 07:35

ソース上でのネストは関係ありません。関数がどうやって呼ばれるかだけが問題です。 jQuery に渡した関数の場合、当然 jQuery がその関数を呼ぶので、jQuery の意図した this 以外にはなりようがありません。 jQueryに渡した関数に名前を付けて、jQuery以外の方法で呼んだときだけ、this が別のものに成り得ます。
pegy

2021/09/29 10:33

int32_t様、maisumakun様 コメントありがとうございます。他の方のコメントも拝見しつつ、調べたのですが、すぐに理解できたことと今、読んでも全く理解できない2つのことがあることがわかりました。 >jQuery に渡した関数の場合、当然 jQuery がその関数を呼ぶので、jQuery の意図した this 以外にはなりようがありません。 jQueryに渡した関数に名前を付けて、jQuery以外の方法で呼んだときだけ、this が別のものに成り得ます。 こちらは、理解ができたと思います。例えばmap()で利用されるthisはJQueryで呼び出されているものではないため、on()で呼び出されるものとはなりえないという理解です。 > thisは使わず、コールバックの引数を経由して明示的に受け取る方法もあります こちらは未だ、理解できていません。具体的にon()やmap()でづやってコールバック引数を設定して、指定のエレメントを指すのかというやり方を調べています。 まだまだ、理解、咀嚼に時間を要すると考えられるため、一旦コメントバックさせていただきました。 宜しくお願い申し上げます。
guest

0

ベストアンサー

横からすみません。
int32_tさんのご回答のコメントを読んで、補足のつもりで回答します。

原則に基づくのかイレギュラーを気にしながら進むべきなのか

使わないのが一番です。

ほとんどの場合、this の値はどのように関数が呼ばれたかによって決定されます (実行時結合)。これは実行時に代入によって設定することはできず、関数が呼び出されるたびに異なる可能性があります。ES5 では bind() メソッドが導入され、関数がどのように呼ばれたかに関係なく this の値を設定するすることができるようになり、ES2015 では、自身では this の結び付けを行わないアロー関数が導入されました

this - JavaScript | MDN

つまり、
アロー式の非束縛 > bindなどのthis束縛 > 実行時結合 > 外側の環境のthisの値
という優先順位になります。

たとえば、こんな感じです。

js

1"use strict"; 2 3function test(){ 4 (()=>console.log(this)).bind({})() // ここではアロー式が優先なので束縛されず、外側を参照する 5} 6 7test() // undefined 8test.bind(null)() // null

以上より私見ですが、バグの温床なのでなるべくthisを使わないことをおすすめします。

投稿2021/09/29 09:10

Lhankor_Mhy

総合スコア36158

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

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

pegy

2021/09/29 11:09

コメントありがとうございます。 正直に申し上げます。2時間リファレンスと格闘したのですが、どうしても理解できません。理由は明らかでアロー関数、bind()、call()、apply()、strictモード、といったものを一度も利用したことがないからです。 因みに読んでいて、グローバルコンテクストでthis === windowがtrueであることが衝撃でした。そのようなthisの指定をしたことがなかったのでそういう仕様なんだ~と感心しながら読んでいました。 あと数日は手を動かしながら読み込まないと腹落ちしないとは思いますが、結果的にthisは容易に利用すべきではないという結論は理解できました。 ただ、恐らくthisを利用する大きな理由(私が初心者だからかのしれませんが)、例えば$(class)のようなものでon()を設定する場合、そのエレメントに対して何かをしたいということがあると思います。そこでonの中で改めて絶対的にその$(class)エレメントを指定することが煩わしいため、簡便性のために存在すると少なくとも関数コンテクストでは理解しておりました。 では、ここでその簡便性を否定しながらも例えば、指定のセレクタを指したいとなった場合、thisを否定した場合、maisumakun様のコメントにもあるようなコールバック引数で受け取る方法?といったアプローチになるのでしょうか? <button class="btn">push</button> <button class="btn">push</button> のようなケースで$('.btn').on('click')でクリックされた要素を指したいとなった場合、仰るアプローチでどうすればいいのか、分からずずっと考えていました・・・ 長文失礼いたします。
maisumakun

2021/09/29 11:36

> $('.btn').on('click')でクリックされた要素を指したいとなった場合、仰るアプローチでどうすればいいのか、分からずずっと考えていました・・・ $('.btn').on('click', e =>)のようにイベントオブジェクトを取って、e.currentTargetが目的のDOMエレメントです(jQueryとして使いたい場合は$(e.currentTarget)としてください)。
pegy

2021/09/29 14:17

ありがとうございます。アロー関数?( e =>)が未だ、適切な利用方法がわからないため $('.btn').on('click', function(e){ console.log($(e.currentTarget)); //中略 }) で確認することができました。 ふーむ、thisがバグの温床になるので、みなさん一般的にeventオブジェクトから対象のエレメントを取得しに行くものなんですね。不慣れなのでコードが少し冗長に見えるのですが、そういうものとして理解いたします!
Lhankor_Mhy

2021/09/30 02:17

> maisumakunさん 補足ありがとうございます。 --- > pegyさん そのような単純な記述ではあまりメリットを感じられないと思います。 でも、以下のようなコードだとうっかりしそうではありませんか? https://jsfiddle.net/Lhankor_Mhy/tohesfp4/
guest

0

技術的なものはともかく、onは触ったものがthisなわけですからセレクタに関わらず
つねにターゲットは1つにしばられます
each/map/filterなど配列をループするような処理はセレクタを走査するので
非常に直感的でむしろ迷うことは無いと思いますがどうでしょう?

たとえばこんなふうにすると、クリック自体は自分を参照するけど
セレクターは全体を掴んでいることがわかるかもしれません

javascript

1<script> 2$(function(){ 3 $('input:button').on('click',function(){ 4 console.log($(this).val()); 5 }).trigger('click'); 6}); 7</script> 8<input type="button" value="1"> 9<input type="button" value="2"> 10<input type="button" value="3">

投稿2021/09/29 08:32

yambejp

総合スコア115012

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

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

pegy

2021/09/29 10:50

コメントいただきありがとうございます。 > each/map/filterなど配列をループするような処理はセレクタを走査するので非常に直感的でむしろ迷うことは無いと思いますがどうでしょう? 確かに直感的には理解得やすいというところは仰る通りかと思います。ともすれば、逆にmap()の中で、全体のセレクタ(命題でいう)$('button')エレメントをthisで相対的に操作したい場合にはどうするのだろうと疑問が湧きあれこれ動かしてみています。もちろん、そんなことをする必要もないし意味はない処理なのですが、直感に反することをするにはということで気になって調べてしまいました。 まだまだ時間がかかりそうであったので、一旦コメントさせて頂きました
maisumakun

2021/09/29 11:40

逆にmap()の中で、全体のセレクタ(命題でいう)$('button')エレメントをthisで相対的に操作したい場合にはどうするのだろうと疑問が湧き mapで呼び出される関数の引数の、2つ目に当該エレメントが来ます。 https://api.jquery.com/map/#map-callback
pegy

2021/09/29 14:10

$('button').on('click',function(){ //alert($(this).text()); //this_1 var get_li = $('li'); get_li.map(function(idx,val){ // alert($(this).text()); //this_2 console.log(val); }) }) と第二引数で得られる結果は当該エレメント$('button')ではなく、$('li')それぞれのエレメントではないでしょうか?もちろんそこからparents()なりfind()で$('button')にたどり着くことはできるのかもしれませんが・・・誤認があれば申し訳ございません。
Lhankor_Mhy

2021/09/30 07:35

> 逆にmap()の中で、全体のセレクタ(命題でいう)$('button')エレメントを いろいろなやり方があると思いますが、イベントハンドラの中で this を何か別の変数に保存して、クロージャで参照するのが一般的のように思います。 $('button').on('click',function(){ //alert($(this).text()); //this_1 const target = this; var get_li = $('li'); get_li.map(function(idx,val){ // alert($(this).text()); //this_2 console.log(target); console.log(val); }) })
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問