document と window の違いは?#
簡単に言えば、dom はオブジェクトであり、win もオブジェクトです。彼らは Web API の中で異なる役割を持っています。
window オブジェクト#
- window オブジェクト
window はウィンドウを指し、ブラウザのウィンドウまたはタブを表し、JavaScript のグローバルオブジェクトです。ブラウザウィンドウを制御するための多くのメソッドとプロパティを提供します。
スコープ:window は最上位のオブジェクトであり、ブラウザ内の任意の JavaScript コードから直接 window およびそのプロパティやメソッドにアクセスできます。
機能:window オブジェクトはブラウザウィンドウのプロパティ(ウィンドウのサイズ、位置など)を含み、また新しいウィンドウを開く、タイマー関数(setTimeout、setInterval)、ブラウザの履歴を制御するなどのウィンドウの動作を制御するためのメソッドを提供します。さらに、全てのグローバル変数とグローバル関数のホストでもあります。
document オブジェクト#
- document オブジェクト
定義:document オブジェクトは window オブジェクトのプロパティであり、ウィンドウに読み込まれた HTML ドキュメントを表し、Document Object Model(DOM)のエントリポイントです。
スコープ:document オブジェクトはドキュメントの内容を操作およびアクセスするために特化されています。例えば、HTML 要素、CSS スタイルなどです。
機能:document オブジェクトはドキュメントの内容にアクセスおよび変更するための多くのメソッドを提供します。要素の内容を取得および設定する、新しい HTML 要素を作成する、クエリセレクタを使用するなどです。document オブジェクトを通じて、ページの内容を動的に変更し、インタラクションを実現できます。
全体として、window オブジェクトはブラウザウィンドウ自体を表し、全てのグローバル JavaScript オブジェクト、関数、変数の親オブジェクトであり、document オブジェクトはウィンドウに読み込まれたドキュメントを表し、全ての HTML ドキュメント要素のコンテナです。実際の開発では、ブラウザウィンドウ自体を操作するのか、ウィンドウ内のドキュメント内容を操作するのかに応じて、window または document を使用することが決まります。
簡単に言えば、dom オブジェクトはドキュメントの内容を操作し、window オブジェクトはブラウザウィンドウのプロパティとメソッドを操作します。したがって、タイマーを設定したり、ウィンドウの変化を監視したりしたい場合は window オブジェクトを使用する必要がありますが、ドキュメントの内容を変更したい場合は document オブジェクトを使用する必要があります。
そのため、実際にはガントチャートの最も重要な問題は、window API と document API の違いがわからなかったことです。私はネイティブの HTML を理解しておらず、この知識が欠けていると、自然にこのロジックを設計することはありません。
本質的には、パッケージ化された API を使うことができるということです。
Dom 流 API 学習#
要素の取得方法#
DOM で要素を取得する主な API は以下の通りです:
-
getElementById()
- 要素の ID を使用して単一の要素を取得します。ID は HTML ドキュメント内で一意である必要があります。
let element = document.getElementById('elementId'); // IDを使用して要素を取得
-
getElementsByClassName()
- 要素のクラス名を使用して要素の集合を取得します。このメソッドは、指定されたクラス名に一致する全ての要素を含む類似配列オブジェクトを返します。
let elements = document.getElementsByClassName('className'); // クラス名を使用して要素の集合を取得
-
getElementsByTagName()
- 要素のタグ名(例えば
div
,p
,a
など)を使用して要素の集合を取得します。同様に、指定されたタグ名に一致する全ての要素を含む類似配列オブジェクトを返します。
let elements = document.getElementsByTagName('tagName'); // タグ名を使用して要素の集合を取得
- 要素のタグ名(例えば
-
querySelector()
- CSS セレクタを使用して最初に一致する要素を取得します。これは非常に強力なメソッドで、複雑な CSS セレクタを使用して要素を特定できます。
let element = document.querySelector('.className'); // CSSセレクタを使用して最初に一致する要素を取得
-
querySelectorAll()
- CSS セレクタを使用して全ての一致する要素の集合を取得します。このメソッドは、指定された CSS セレクタに一致する全ての要素を含む
NodeList
オブジェクトを返します。
let elements = document.querySelectorAll('.className'); // CSSセレクタを使用して全ての一致する要素を取得
- CSS セレクタを使用して全ての一致する要素の集合を取得します。このメソッドは、指定された CSS セレクタに一致する全ての要素を含む
-
closest()
- 要素自身から始めて、その祖先要素の中で(自身を含む)、指定された CSS セレクタに一致する最初の要素を見つけます。このメソッドは、要素の最近の親の一致を見つけるのに非常に便利です。下から上に探します。
let closestElement = element.closest('.className'); // 要素の祖先の中で最近の指定されたセレクタに一致する要素を見つける
-
children
- 要素の子要素の集合を取得します。テキストノードやコメントノードは含まれません。これは要素オブジェクトのプロパティで、直接の子要素の HTML 集合を返します。
let childElements = parentElement.children; // parentElementの全ての直接の子要素を取得
-
childNodes
- 要素の全ての子ノードを取得します。要素ノード、テキストノード、コメントノードを含みます。これも要素オブジェクトのプロパティで、ノードリストを返します。
let childNodes = parentElement.childNodes; // parentElementの全ての子ノードを取得(テキストとコメントを含む)
-
parentElement
とparentNode
- 要素の親要素を取得します。
parentElement
は親要素ノードを返し、parentNode
はテキストノードやコメントノードを含む任意のタイプの親ノードを返すことができます。
let parent = childElement.parentElement; // childElementの親要素を取得 let parentNode = childElement.parentNode; // childElementの親ノードを取得
- 要素の親要素を取得します。
-
nextSibling
とpreviousSibling
- 要素の次の同級ノードと前の同級ノードをそれぞれ取得します。これらのプロパティが返すのは、要素ノード、テキストノード、コメントノードを含む任意のタイプのノードです。
let nextNode = element.nextSibling; // elementの次の同級ノードを取得 let prevNode = element.previousSibling; // elementの前の同級ノードを取得
-
nextElementSibling
とpreviousElementSibling
nextSibling
とpreviousSibling
に似ていますが、これらのプロパティは要素ノードのみを返し、テキストノードやコメントノードは無視します。
let nextElement = element.nextElementSibling; // elementの次の同級要素を取得 let prevElement = element.previousElementSibling; // elementの前の同級要素を取得
-
firstChild
とlastChild
- 要素の最初の子ノードと最後の子ノードをそれぞれ取得します。これらの子ノードは、要素ノード、テキストノード、コメントノードを含む任意のタイプのノードです。
let first = parentElement.firstChild; // parentElementの最初の子ノードを取得 let last = parentElement.lastChild; // parentElementの最後の子ノードを取得
-
firstElementChild
とlastElementChild
firstChild
とlastChild
に似ていますが、これらのプロパティは要素ノードのみを返し、テキストノードやコメントノードは無視します。
let firstElement = parentElement.firstElementChild; // parentElementの最初の子要素を取得 let lastElement = parentElement.lastElementChild; // parentElementの最後の子要素を取得
これらの API を総合的に活用することで、DOM ツリーを効果的に遍歴し、操作し、ページ構造を柔軟に制御できます。
これらの API を使用することで、異なる条件やニーズに応じて、DOM ツリー内で単一または複数の要素を柔軟に取得できます。
要素の作成方法#
要素を作成する#
document.createElement('tag')
テキストノードを作成する#
document.createTextNode('text')
テキストノードとは何ですか?
テキストノードは HTML 内のテキストであり、例えば p タグ内のテキストや a タグ内のテキストなどです。
createTextNode はどのように使用しますか?
var text = document.createTextNode('text')
これはどのような効果ですか?
<p>text</p>
ここでの text はその文字の内容です。
要素を追加する方法#
要素を追加する#
parent.appendChild(child)
これはどのような効果ですか?
<div>
<p>text</p>
</div>
要素を挿入する#
parent.insertBefore(newNode, referenceNode)
例を挙げると
var parent = document.getElementById('parent')
var newNode = document.createElement('p')
var referenceNode = document.getElementById('reference')
parent.insertBefore(newNode, referenceNode)
これはどのような効果ですか?
<div id="parent">
<p>newNode</p>
<p id="reference">referenceNode</p>
</div>
referenceNode はどのような役割を果たしますか?
referenceNode は参照ノードであり、参照ノードの前に新しいノードを挿入する役割を果たします。
要素を削除する方法#
要素を削除する#
parent.removeChild(child)
例を挙げると
var parent = document.getElementById('parent')
var child = document.getElementById('child')
parent.removeChild(child)
これはどのような効果ですか?対比を示してください
<div id="parent">
<p id="child">child</p>
</div>
<div id="parent">
</div>
要素の内容を変更する方法は?#
DOM(文書オブジェクトモデル)で要素の内容を変更する主な API は以下の通りです:
-
innerText
とtextContent
これらのプロパティは、要素のテキスト内容を取得または設定するために使用できます。innerText
は要素とその子要素の「レンダリング」されたテキスト内容を反映し、textContent
は要素内の全ての子ノードの内容を取得または設定します。element.innerText = '新しいテキスト内容'; // 要素の可視テキストを設定 let content = element.innerText; // 要素の可視テキストを取得 element.textContent = '新しい全てのテキスト内容'; // 要素の全てのテキストを設定、全ての子ノードを含む let fullContent = element.textContent; // 要素の全てのテキストを取得、全ての子ノードを含む
-
innerHTML
innerHTML
プロパティは、要素内の HTML 内容を取得または設定するために使用できます。innerText
やtextContent
とは異なり、innerHTML
は全ての HTML タグを含みます。element.innerHTML = '<strong>太字のテキスト</strong>'; // 要素内のHTML内容を設定 let htmlContent = element.innerHTML; // 要素内のHTML内容を取得
-
outerHTML
outerHTML
プロパティは、要素自身とその全ての子ノードを含む HTML を取得または設定できます。element.outerHTML = '<div><strong>新しい要素とその内容</strong></div>'; // 要素とその内容を置き換える
-
createElement
とappendChild
/replaceChild
これらのメソッドは、新しい DOM 要素を作成し、文書に挿入するために使用されます。createElement
は新しい要素ノードを作成し、appendChild
は作成したノードを親ノードの子ノードリストの末尾に追加し、replaceChild
は親ノードの子ノードを置き換えます。let newElement = document.createElement('div'); // 新しいdiv要素を作成 newElement.innerText = 'これは新しく作成された要素です'; // 新要素のテキスト内容を設定 parentElement.appendChild(newElement); // 新要素をparentElementの子ノードとして追加 let anotherElement = document.createElement('span'); // 別の要素を作成 parentElement.replaceChild(anotherElement, newElement); // 親要素内の子要素を置き換える
これらの API を使用することで、DOM 内の要素の内容や構造を簡単に変更できます。
DOM 内の要素のスタイルや属性を変更する主な API は以下の通りです:
-
スタイルの変更:
style
プロパティ- 各 DOM 要素には
style
プロパティがあり、JavaScript を通じて要素のスタイルを直接変更できます。要素のstyle
プロパティ内の CSS プロパティを設定することでスタイルを変更できます。
element.style.backgroundColor = 'red'; // 要素の背景色を赤に設定 element.style.fontSize = '20px'; // 要素のフォントサイズを20ピクセルに設定
- 各 DOM 要素には
-
クラスの変更:
classList
プロパティclassList
は、要素のクラス名の集合を操作するための簡単な方法を提供します。一般的なメソッドにはadd()
、remove()
、toggle()
、contains()
があります。
element.classList.add('new-class'); // 新しいクラス名を追加 element.classList.remove('old-class'); // クラス名を削除 element.classList.toggle('active'); // 存在すればそのクラス名を削除し、存在しなければ追加
-
属性の設定と取得:
setAttribute()
とgetAttribute()
- これらのメソッドは、要素の属性を設定および取得するために使用されます。属性は標準の HTML 属性(例えば
id
、src
、href
など)やカスタム属性である可能性があります。
element.setAttribute('data-custom', 'value'); // カスタム属性を設定 let value = element.getAttribute('data-custom'); // このカスタム属性の値を取得
- これらのメソッドは、要素の属性を設定および取得するために使用されます。属性は標準の HTML 属性(例えば
-
属性を直接変更
id
、src
、href
などの一般的な HTML 属性については、要素オブジェクトを通じて直接取得および設定できます。
element.href = 'https://example.com'; // 要素のhref属性を直接設定 let elementId = element.id; // 要素のid属性を直接取得
これらの API を使用することで、JavaScript 内で DOM 要素のスタイルや属性を簡単に変更し、動的なページ効果を実現できます。
要素を置き換える方法#
要素を置き換える#
DOM 操作における要素の置き換えには、以下の一般的な API が含まれます:
-
replaceChild(newChild, oldChild)
- これは親ノード上で呼び出されるメソッドで、親ノード内の旧子ノードを新しい子ノードに置き換えるために使用されます。
newChild
は挿入する新しいノードで、oldChild
は置き換えられる旧ノードです。
parentNode.replaceChild(newElement, oldElement); // parentNode内のoldElementをnewElementに置き換える
- これは親ノード上で呼び出されるメソッドで、親ノード内の旧子ノードを新しい子ノードに置き換えるために使用されます。
-
replaceWith(...)
replaceWith()
メソッドは、指定されたノードまたは HTML やテキスト文字列を使って DOM ノード(または複数のノード)を置き換えることを可能にします。このメソッドは、置き換えられるノード上で直接呼び出されます。
oldElement.replaceWith(newElement); // oldElementをnewElementに置き換える
-
insertBefore()
とremoveChild()
またはremove()
を組み合わせて置き換えを実現- 直接的な置き換えメソッドではありませんが、新しいノードを旧ノードの前に挿入し、その後旧ノードを削除することで置き換えを実現できます。
parentNode.insertBefore(newElement, oldElement); // newElementをoldElementの前に挿入 parentNode.removeChild(oldElement); // oldElementを削除し、置き換え効果を実現 // または、環境がサポートしている場合は、より簡潔にoldElement.remove()を使用できます。 oldElement.remove();
-
outerHTML
を使用- 要素の
outerHTML
プロパティを設定することで、要素自身とその内容全体を直接置き換えることができます。この方法では、親ノードを取得する必要はありません。
oldElement.outerHTML = '<div id="newElement">新しい内容</div>'; // oldElementを新しいHTML内容で置き換える
- 要素の
これらの API は、DOM 内の要素を置き換える柔軟な方法を提供し、異なるシナリオやニーズに応じて適切な方法を選択できます。
要素にイベントを追加する方法#
DOM 内で要素のイベントを処理する主な API は以下の通りです:
-
addEventListener(event, handler, [options])
- 指定された要素にイベントリスナーを追加するために使用されます。
event
はリッスンするイベントタイプ(例えば"click"
、"mouseover"
など)、handler
はイベントが発生したときに呼び出される関数、options
は詳細なイベントリスニング動作を指定するためのオプションのパラメータです。
element.addEventListener('click', function() { console.log('要素がクリックされました'); });
- 指定された要素にイベントリスナーを追加するために使用されます。
-
removeEventListener(event, handler, [options])
- 以前に
addEventListener
で追加したイベントリスナーを削除するために使用されます。handler
は、リスナーを追加したときに使用した同じ関数参照でなければなりません。
function handleClick() { console.log('要素がクリックされました'); } element.addEventListener('click', handleClick); // 後でリスナーを削除 element.removeEventListener('click', handleClick);
- 以前に
-
dispatchEvent(event)
- 指定された要素上でイベントをトリガーするために使用されます。
event
はEvent
オブジェクトのインスタンスであり、new Event()
を使用して作成できます。
let event = new Event('customEvent'); element.dispatchEvent(event); // カスタムイベントをトリガー
- 指定された要素上でイベントをトリガーするために使用されます。
-
プロパティを通じてイベントハンドラーを直接割り当てる
- 要素のイベントハンドラー属性にイベント処理関数を直接割り当てることができます。例えば、
onclick
はクリックイベントに対応します。
element.onclick = function() { console.log('要素がクリックされました'); };
- 要素のイベントハンドラー属性にイベント処理関数を直接割り当てることができます。例えば、
-
on
プレフィックスの属性を使用してイベント処理関数を設定onclick
の他にも、onmouseover
、onkeydown
など、on
で始まる属性を設定することで多くの他のイベントに対して処理関数を追加できます。
element.onmouseover = function() { console.log('マウスが要素の上にあります'); };
-
Event
オブジェクトの使用- イベント処理関数内の
event
パラメータはEvent
オブジェクトのインスタンスであり、イベントに関する情報(イベントが発生した要素、イベントタイプ、その他の特定のイベントに関連するプロパティやメソッド)を提供します。
element.addEventListener('click', function(event) { console.log('クリックが発生したのは ' + event.target.tagName + ' 要素上です'); });
- イベント処理関数内の
-
preventDefault()
- イベントオブジェクトの
preventDefault()
メソッドは、イベントのデフォルトの動作を防ぐために使用されます。これは、リンクをクリックしたときにページがジャンプしないようにしたり、フォームを送信したときにページが再読み込みされないようにする場合に非常に便利です。
element.addEventListener('click', function(event) { event.preventDefault(); // リンクのデフォルトのジャンプ動作を防ぐ });
- イベントオブジェクトの
-
stopPropagation()
- イベントが親要素にバブルアップするのを防ぐために使用されます。イベントバブリングとは、イベントが最も深いノードから始まり、次第に浅いノードに向かって伝播するプロセスを指します。
element.addEventListener('click', function(event) { event.stopPropagation(); // イベントのバブリングを停止 });
-
イベント委任
- イベントバブリングの特性を利用して、各子要素ではなく親要素にイベントリスナーを設定できます。イベントが子要素で発生し、親要素にバブリングすると、イベントの
target
属性を確認してどの子要素がイベントをトリガーしたかを特定できます。
parentElement.addEventListener('click', function(event) { if (event.target && event.target.matches('button.child')) { console.log('子ボタンがクリックされました'); } });
- イベントバブリングの特性を利用して、各子要素ではなく親要素にイベントリスナーを設定できます。イベントが子要素で発生し、親要素にバブリングすると、イベントの
-
capture
イベントキャプチャ- イベント処理の第 3 のパラメータ
options
で、capture
をtrue
に設定することで、イベント処理器がバブリング段階ではなくキャプチャ段階で実行されるように指定できます。イベントキャプチャは、イベントが最外層から始まり、次第に深いノードに向かって伝播するプロセスを指します。
element.addEventListener('click', function() { console.log('キャプチャ段階のイベント処理'); }, {capture: true});
- イベント処理の第 3 のパラメータ
-
once
オプションaddEventListener
の第 3 のパラメータで、once: true
を設定することで、イベント処理器が一度だけ実行され、その後自動的に削除されます。
element.addEventListener('click', function() { console.log('このイベント処理器は一度だけ実行されます'); }, {once: true});
これらの API を使用することで、DOM 要素に対してイベントを柔軟に追加、削除、トリガーし、豊富なインタラクション効果を実現できます。
ライフサイクル#
DOM(文書オブジェクトモデル)と Window オブジェクトは、Web ページのライフサイクルにおいて重要な役割を果たします。以下に、DOM と Window のライフサイクルに関連する API を紹介します:
-
Window のライフサイクルイベント:
-
load
イベント- ページ全体とすべての依存リソース(スタイルシートや画像など)が完全に読み込まれたとき、
window
オブジェクトはload
イベントをトリガーします。
window.addEventListener('load', function() { console.log('ページが完全に読み込まれました'); });
- ページ全体とすべての依存リソース(スタイルシートや画像など)が完全に読み込まれたとき、
-
DOMContentLoaded
イベント- 初期の HTML ドキュメントが完全に読み込まれ、解析が完了したとき、スタイルシート、画像、子フレームの読み込みを待つ必要はなく、
document
オブジェクトはDOMContentLoaded
イベントをトリガーします。
document.addEventListener('DOMContentLoaded', function() { console.log('DOM内容が読み込まれました'); });
- 初期の HTML ドキュメントが完全に読み込まれ、解析が完了したとき、スタイルシート、画像、子フレームの読み込みを待つ必要はなく、
-
unload
イベント- ユーザーが現在のページを離れると、
window
オブジェクトはunload
イベントをトリガーします。このイベントは、ポップアップウィンドウを閉じるなどのクリーンアップ作業に使用できます。
window.addEventListener('unload', function() { console.log('ユーザーがページを離れました'); });
- ユーザーが現在のページを離れると、
-
beforeunload
イベント- ウィンドウ、ドキュメント、またはそのリソースがアンロードされる直前にトリガーされます。ユーザーに現在のページを離れるかどうかを確認するために使用でき、通常は未保存の変更を保存するようにユーザーに通知します。
window.addEventListener('beforeunload', function(event) { event.returnValue = '未保存の変更があります。離れてもよろしいですか?'; });
-
-
リクエストアニメーションフレーム(Request Animation Frame):
-
requestAnimationFrame(callback)
- ブラウザが再描画する前に特定のコードを呼び出す方法を提供し、アニメーションやページの再描画などを実行するために使用されます。このメソッドは、従来の
setInterval
よりも効率的で、アニメーションをよりスムーズに実行できます。
function animate() { // アニメーションコード requestAnimationFrame(animate); } requestAnimationFrame(animate);
- ブラウザが再描画する前に特定のコードを呼び出す方法を提供し、アニメーションやページの再描画などを実行するために使用されます。このメソッドは、従来の
-
-
ページ可視性 API(Page Visibility API):
- この API は、
visibilitychange
イベントとdocument.hidden
属性を提供し、ページがユーザーに対して可視かどうかを検出するために使用されます。これは、ページのパフォーマンスとユーザーエクスペリエンスを最適化するのに特に役立ちます。例えば、ページが見えないときに動画の再生を一時停止したり、アニメーションを停止したりできます。
document.addEventListener('visibilitychange', function() { if (document.hidden) { console.log('ページが見えなくなりました'); } else { console.log('ページが見えるようになりました'); } });
- この API は、
-
パフォーマンス監視 API(Performance API):
performance
オブジェクトは、現在のページに関連するパフォーマンスデータにアクセスすることを許可します。例えば、performance.timing
を使用して、ページの読み込み、解析などの異なる段階の時間を分析できます。
window.addEventListener('load', function() { setTimeout(function() { const timing = performance.timing; const loadTime = timing.loadEventEnd - timing.navigationStart; console.log('ページの読み込み時間:' + loadTime); }, 0); });
-
resize
イベント:- ブラウザウィンドウのサイズが変更されると、
window
オブジェクトはresize
イベントをトリガーします。これは、ページのレイアウトを調整したり、ウィンドウサイズの変化に応じて他の操作を実行するために使用できます。
window.addEventListener('resize', function() { console.log('ウィンドウのサイズが変更されました'); });
- ブラウザウィンドウのサイズが変更されると、
-
scroll
イベント:- ユーザーがページをスクロールすると、
scroll
イベントがトリガーされます。これは、「遅延読み込み」(画像などのコンテンツを遅れて読み込む)を実現したり、ナビゲーションバーのスタイルを動的に変更したりするために使用できます。
window.addEventListener('scroll', function() { console.log('ページがスクロールされました'); });
- ユーザーがページをスクロールすると、
-
focus
とblur
イベント:- ページまたはページ内の要素がフォーカスを得たり失ったりすると、
focus
とblur
イベントがトリガーされます。これは、フォーム入力のユーザーエクスペリエンスを改善したり、アプリケーション内でキーボードショートカットを管理したりするために使用できます。
window.addEventListener('focus', function() { console.log('ウィンドウがフォーカスを得ました'); }); window.addEventListener('blur', function() { console.log('ウィンドウがフォーカスを失いました'); });
- ページまたはページ内の要素がフォーカスを得たり失ったりすると、
これらの API を組み合わせて使用することで、開発者は Web アプリケーションの動作とパフォーマンスをより細かく制御し、ユーザーのインタラクション体験を向上させることができます。
これらのライフサイクルイベントをリッスンし、処理することで、Web ページの読み込み、レンダリング、アンロードプロセスをより良く制御し、ユーザーエクスペリエンスを向上させることができます。