JavaScriptで自身の要素よりも上の階層に特定の要素があるかどうかを判別したり、その要素を指定してDOM操作することがよくあります。そのような場合にはclosest()メソッドを利用するのが一般的です。
closest()メソッドの使い方
DOM構造において指定の要素よりも親要素よりも上の階層にあるエレメントを「先祖要素」といいます。例えば以下のようなHTML構造があるとします。
<div class="level3">
<div class="level2">
<div class="level1">
<p class="level0">ここの要素</p>
</div>
</div>
</div>この場合、<p>の親要素は<div class="level1">になり先祖要素は<div class="level2">と<div class="level3">になります。
このp.level0を基準として、その上の階層にあるdiv.level3を指定する場合には次のようにclosest()メソッドを使用します。
let ancestorDOM = document.getElementsByClassName('level0')[0].closest('.level3');上記サンプルで注意すべき点が2つあります。
1つは、getElementsByClassNameはclass名がlevel0の要素をすべて取得するので[0]のように何番目かを指定します。(0は先頭を示します)
getElementByIdで指定する場合には、原則としてidはページ内に1つしかないはずですので単純に
document.getElementsById('anyID').closest('.level3');のようになり、[0]は不要です。
もう1つは、closest(セレクタ) で指定するセレクタは「セレクタ」なのでclassの場合は「.」idの場合は「#」を忘れないように気を付けて下さい。もし単に<div>であればclosest('div')になります。
closest()で取得した要素にクラスを付けたい場合
さきほどのサンプルで取得したエレメントにクラスを付けたいときは以下のようにします。
let ancestorDOM = document.getElementsByClassName('level0')[0].closest('.level3');
ancestorDOM.classList.add('newClass');jQueryでは.addClass()というメソッドがありますが、プレーンなJavaScriptでは.classList.add('クラス名')のようにしてクラスを付与します。
closest()を使って先祖要素が存在するか判別したい場合
特定の要素に先祖要素が存在するかどうかを判別するときは以下のようにします。
let ancestorDOM = document.getElementsByClassName('level0')[0].closest('.notExist');
if(ancestorDOM == null){
// 存在しない場合の処理
} else {
// 存在する場合の処理
}closest()メソッドは存在しない場合はnullを返すので、nullかどうかで判別するとスマートですね。
(参考:https://developer.mozilla.org/ja/docs/Web/API/Element/closest#%E8%BF%94%E5%80%A4)
まとめ
例えば「指定の要素の先祖にlevel3というクラスの要素があれば、newClassというクラスをそこに付与したい」場合は以下のようになります。
let ancestorDOM = document.getElementsByClassName('level0')[0].closest('.level3');
if(ancestorDOM == null){
// 存在しない場合の処理
} else {
// 存在する場合の処理
ancestorDOM.classList.add("newClass");
}ずっと簡単にclosest()メソッドが使えますね。

