12
3

そろそろ、find()・children()・closest()・parent()・parents()・filter() を迷わず使いたい

Posted at

「も〜、、、 何回同じこと調べるねん!」

ということで、自分のためにも覚書です。

find()filter()ってどう違うんだっけ?」
closest()ってセレクタ自身も取得対象に含んでたっけ?」

この曖昧な記憶をスッキリさせたいと思います。

find()・children()・closest()・parent()・parents()・filter()それぞれの違いと使い方

セレクタ付近の要素を取得するために使うjQueryのメソッドは、大きく分けて

① 子・孫要素を取得するメソッド
② 親・祖先要素を取得するメソッド
③ 指定した選択肢の中でフィルタリングをかけて取得するメソッド

の3つに分類できるかと思います。

① 子・孫要素を取得するメソッド

1. find()

指定した要素よりも中の要素から、条件にマッチする全ての子孫要素を取得します。

html
<div class="parent">
    <div class="child active">子要素</div>
    <div class="child">
	    <div class="grandchild">孫要素</div>
    </div>
</div>

以下は、parentクラス要素の全ての子孫要素の中から、activeクラスを持つ要素を取得する場合。1つ目の子要素が取れています。

find.js
$('.parent').find('.active').css('background-color', 'yellow');

次は、parentクラス要素の全ての子孫要素の中からchildクラスを持つ要素を探す場合。
find()は条件にマッチする全ての子孫要素を取得するので、<div class="child active">子要素</div>と、<div class="child"><div class="grandchild">孫要素</div></div>の2つが取れています。

find.js
$('.parent').find('.child').css('background-color', 'yellow');

そして、parentクラスの中でgrandchildクラスを持つ要素を探す場合。子要素より下の階層にある孫要素も取得できています。

find.js
$('.parent').find('.grandchild').css('background-color', 'yellow');

2. children()

children()は、指定した要素の直下の子要素だけを取得するメソッドです。
直下の子要素だけを対象にするので、孫要素やそれ以上の深さの要素を取得できない点でfind()とは異なります。

children.js
$('.parent').children('.child').css('background-color', 'yellow');

上のように、子要素は問題なく取得できるのですが、

children.js
$('.parent').children('.grandchild').css('background-color', 'yellow');

としても、直下の子要素にgrandchildクラスは存在しないので、要素を見つけることができません。

② 親・祖先要素を取得するメソッド

1. parent()

parent()は、指定した要素の直近の親要素だけを取得するメソッドです。

html
<div class="grandparent active">祖先要素
   <div class="parent active">親要素
      <div class="child">子要素</div>
   </div>
</div>
parent.js
$('.child').parent('div').css('border', '5px solid red');

今度は、取得できた要素に赤枠をつけています。childクラスの直近の親要素のdivタグは<div class="parent active">なので、そのエリアに赤枠がつきました。

直近の階層しか取得できないという意味ではchildren()と対になるメソッドです。ただ、1つの親要素に対して複数の子要素が存在しうるのに対し、1つの子要素に親は1つなので、原則、指定した要素の数だけの要素がparent()の取得できる選択肢になるという点でやや異なります。

2. parents()

parents()は、指定した要素の全ての祖先要素が取得範囲になります。今度は親より遠い祖先も取得範囲になり、「全て」取得できるので、複数形になるんですね。

parents.js
$('.child').parents('div').css('border', '5px solid red');

childクラス要素の親以上に当たるdivタグは<div class="parent active"><div class="grandparent active">の2つなので、二重に赤枠がついています。

3. closest()

closest()は、指定した要素から見て、最も近い祖先要素を探索し、条件に一致する最初の要素を選択します。

closest.js
$('.child').closest('div').css('border', '5px solid red');

ここで、parent()parents()と違うのは、取得の選択肢に自身も含むということ。
親方向に2階層以上遡れるという意味ではparentsと似ていて、条件を満たす1つを取得するという意味ではparentと同じですが、自身が条件に一致する場合、自身を選ぶことができます。自身が条件に合わない場合は、順に祖先を辿り、一番最初にマッチするものを取得します。

なので、例えば以下のようにすると、親以上の中で一番近いactiveクラスの要素を取得するので、

closest.js
$('.child').closest('.active').css('border', '5px solid red');

と、直近の親要素を取得します。
これが、parents()に置き換えると、親以上のactiveクラスを持つ要素全てが取得できるので、親要素と祖先要素の周りに二重に枠がつくというわけです。

③ "ちょっと異質" 指定した選択肢の中でフィルタリングをかける filter() メソッド

filter() は、自分で指定した選択肢の中から、指定した条件にマッチする要素だけを取得するメソッドです。

私の認識としては、その名の通り、「フィルター」。
絞り込みで要素を探していくイメージです。指定した要素の内、条件に当てはまるものを探します。親子関係や個数は関係ありません。とにかくフィルターに引っかかりさえすれば良いのです。

html
<div class="container">
	<ul>
	    <li class="item">Item 1</li>
	    <li class="item">Item 2</li>
	    <li class="item active">Item 3</li>
	    <li class="item">Item 4</li>
	</ul>
</div>
filter.js
$('li').filter('.active').css('background-color', 'yellow');

この場合、liタグ全て(4つ)を選択肢として指定して、その中でactiveクラスであるという条件を満たすものが取得できます。

つまり、以下のようにitemクラスであることを取得の条件にすれば、全てのliタグが条件を満たすので、4つとも取得されます。

filter.js
$('li').filter('.item').css('background-color', 'yellow');

逆にfilter()のセレクタにulを指定してしまうと、itemクラスを満たすulタグはないので、もちろん何も取得できません。

filter.js
$('ul').filter('.item').css('background-color', 'yellow');

子孫取得系とfilter()、ちょっとややこしい。 違いを整理

個人的にやや混乱したことを整理して以下にまとめます。主に、filter()find()children()って具体的にどう違う?というお話です。

先ほどの例で、liタグの内からitemクラスを検索すると、itemクラスである要素が全て取れました。

filter.js
$('li').filter('.item').css('background-color', 'yellow');

しかし、この指定方法はfind()だと機能しません。find()は自分より中の階層にいる子孫要素しか対象にならないので、find()のセレクタにliタグを指定した時点で、liタグ要素を取得することはできないのです。

find.js
$('li').find('.item').css('background-color', 'yellow');

find()で同様にitemクラスを探したいなら、ひとつ上(親)のulタグを指定するとOKです。

find.js
$('ul').find('.item').css('background-color', 'yellow');

ちなみに以下にしても結果は同じです。find()は孫以下も取得対象でしたね。

find.js
$('.container').find('.item').css('background-color', 'yellow');

ただし、children()は違います。直下の子要素しか取得できません。containerクラスの直下の子要素はulタグになるので、liタグを取得できないのです。

children.js
$('.container').children('.item').css('background-color', 'yellow');

children()でliタグのitemクラス要素を取得したいなら、直近の親要素であるulタグをセレクタに指定する必要があります。

children.js
$('ul').children('.item').css('background-color', 'yellow');

無事取得できました。以上、混乱しそうなパターンを記してみました。

まとめ

メソッド 検索対象 結果
find() 全ての子孫要素 子孫要素の中から条件にマッチする要素全て
children() 直下の子要素のみ 条件にマッチする直下の子要素全て
parent() 直近の親要素のみ 条件にマッチする直近の親要素
parents() 全ての祖先要素(自身は含まない) 祖先要素の中から条件にマッチする要素全て
closest() 全ての祖先要素(自身含む) 指定した要素から見て、条件にマッチする最初の(=自身から一番近い)要素
filter() 指定した要素 条件にマッチする要素全て

p.s.
これでしばらくは「 find() filter() 違い 」と、Google先生に何度も同じことを聞かなくて済みそうです。

12
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3