Open13

JS基礎のメモ

sayasaya

DOMから要素を選択するためのメソッドだが、何が違う?

  • querySelector
  • getElementById
  • getElementsByClassName

getElementById

指定されたID属性を持つ要素を返す。
常に単一の要素(またはnull)を返す。

例:document.getElementById('myId')はIDがmyIdの要素を返す。

getElementsByClassName

特性

指定されたクラス名を持つすべての要素をHTMLCollectionとして返す。
結果は動的。(DOMに変更があった場合、HTMLCollectionもそれをリアルタイムで反映するということ)

例:document.getElementsByClassName('myClass')はクラスmyClassを持つすべての要素を返す。

使用ケース

  • クラス名を持つすべての要素に対して何らかの操作を行いたいとき。
  • 例えば、特定のクラス名を持つすべての要素のスタイルを一度に変更する場合など。

querySelector

特性

指定されたセレクターに一致する最初の要素を返す。
より強力なセレクターの機能を利用できるので、ID、クラス、属性などの複雑なセレクターの組み合わせを使用することができる。
結果は静的。

CSSセレクターの全範囲を使用して要素を選択できるため、最も柔軟性がある。

例:document.querySelector('.myClass')はクラスmyClassを持つ最初の要素を返す。
document.querySelector('#myId')はIDがmyIdの要素を返す。

使用ケース

  • 特定のセレクターに一致する要素を1つだけ取得したいとき。
  • 複雑なセレクターの組み合わせを利用して要素を取得したいとき。

もっと分かりやすく🤔

例:

document.getElementsByClassName('nav-click-container'):

このメソッドは、指定されたクラス名を持つすべての要素を取得する。

返されるのはHTMLCollectionという動的なオブジェクトで、このオブジェクトはDOMの変更をリアルタイムで反映する。

したがって、ページ上にnav-click-containerというクラス名を持つ要素が3つある場合、このメソッドはその3つの要素を含むHTMLCollectionを返す。

document.querySelector('.nav-click-container'):

このメソッドは、指定されたセレクターに一致する最初の要素を取得する。

返されるのは単一の要素

したがって、ページ上にnav-click-containerというクラス名を持つ要素が3つある場合、このメソッドは最初の要素のみを返す。

querySelectorはより強力なセレクターの機能を利用でき、ID、クラス、属性などのさまざまなセレクターを組み合わせることができる。

要するに、最も顕著な違いは以下の2点!!

getElementsByClassNameはHTMLCollectionを返し、指定されたクラス名を持つすべての要素を含む。
querySelectorは単一の要素を返し、指定されたセレクターに一致する最初の要素のみを取得する。

console.log(getElementsByClassName)

console.log(querySelector)

どう使い分ければいいんだ?

  • すべての一致する要素に何かを適用したい場合
    getElementsByClassNamegetElementsByTagNamequerySelectorAllを使用!

  • 特定の要素にのみアクセスしたい場合
    querySelectorgetElementByIdなどを使用!

  • 複雑なセレクタを使用して要素にアクセスしたい場合
    querySelectorquerySelectorAllを使用!

  • 動的なコレクションが必要な場合
    getElementsByClassNamegetElementsByTagNameを使用!

sayasaya

eventオブジェクト

JavaScriptのイベントリスナーがイベントをキャッチすると、
それに関連する情報を含むeventオブジェクトが自動的に生成される。

eventオブジェクトには、発生したイベントの種類、イベントのターゲット、
キーの押下やマウスの位置などのイベントに関連する詳細な情報が含まれている!

eventオブジェクトの一部のプロパティ

  • event.type: イベントの種類(例: "click", "change"など)
  • event.target: イベントが発生したDOM要素
  • event.currentTarget: 現在のイベントリスナーがアタッチされているDOM要素
  • event.preventDefault(): デフォルトのイベント動作をキャンセルするためのメソッド(例: <a>タグのクリックによるページ遷移の防止)
  • event.stopPropagation(): イベントの伝播を停止するためのメソッド

event.target

イベントが発生した特定のDOM要素を指す。

例:フォーム内のいくつかの入力フィールドがあり、これらのフィールドのいずれかが変更された場合、changeイベントのevent.targetは変更された入力フィールド自体を指す。

event.target.value

特にフォームの要素(例: <input>, <select>, <textarea>など)に関連して、その要素の現在の値を取得するために使用される。

例:次のようなテキスト入力フィールドがあるとする。

<input type="text" id="nameField" value="John">

この入力フィールドの内容が変更されるたびに、その新しい値を取得するには、、

document.getElementById('nameField').addEventListener('change', function(event) {
    console.log(event.target.value); // ユーザーが入力した新しい値が表示される
});

event.target.valueを使用すると、イベントが発生した時点での要素の値にアクセスすることができる!

sayasaya

同一オリジンとは?

Webセキュリティの文脈で使われる概念で、あるウェブページからのリクエストが、
別のウェブページやサーバーとどのように相互作用できるかを制限するポリシーのこと。

具体的には、以下の3つの組み合わせが同じであるかどうかに基づく!

  1. プロトコル (例: http, https)
  2. ドメイン (またはホスト名) (例: example.com, mywebsite.org)
  3. ポート番号 (例: 80, 443)

「同一オリジンポリシー」(Same Origin Policy)

異なるオリジンからのリソースに対する直接的なアクセスを制限するもの。
これにより、悪意のあるサイトがユーザーのデータを盗むのを防ぐことができる。

例:
http://example.com のページから、同じく http://example.com のAPIやデータにアクセスするのは問題なし!これは同一オリジン

http://example.com のページから https://example.com (異なるプロトコル) や http://api.example.com (異なるサブドメイン)、http://example.com:8080 (異なるポート番号) への直接的なアクセスは制限される。これは異なるオリジン

これがなければ、ログインしている銀行のサイトの情報が、後で訪れる別の悪意のあるサイトによって盗まれるといったような、リスクが高まる👀

同一オリジンポリシーにはいくつかの回避方法があり、
CORS (Cross-Origin Resource Sharing) という機能を使って、サーバー側で特定のオリジンからのアクセスを許可する設定を行うことができる!!

sayasaya

innerTextと innerHTML

innerText

内容の取得・設定:innerText は、要素の表示されているテキスト内容を取得したり、新しいテキストを設定する際に使用される。

スタイルを考慮:innerText は、CSSで隠されたテキストを取得しない点で textContent と異なる。
改行を考慮: 要素内の改行や配置に従って、テキストを取得する。

innerHTML

HTMLの取得・設定:innerHTML は、要素の内部のHTMLを取得したり、新しいHTMLを設定する際に使用される。

スクリプト実行: 新しいHTMLに含まれるスクリプトは、そのHTMLを innerHTML に設定する際に実行されません。

安全性:innerHTML を使用する際には注意が必要!ユーザーからの入力をそのまま innerHTML に設定すると、クロスサイトスクリプティング(XSS)というセキュリティ上のリスクが生じる可能性がある。

element.innerHTML = someHTMLString; のように使って、要素の中身を新しいHTMLで置き換えることができる!

比較例:

const div = document.createElement('div');
div.innerHTML = '<span>Hello, <strong>World!</strong></span>';

console.log(div.innerText); // "Hello, World!"
console.log(div.innerHTML); // "<span>Hello, <strong>World!</strong></span>"

innerText はHTMLタグを解釈せず、純粋なテキスト内容だけを取得。
一方、innerHTML は要素の内部のHTML構造を取得!

sayasaya

Promiseとは?

非同期処理の結果を表すオブジェクトの一つ。
時間がかかる処理(例: データベースへの問い合わせや、外部サイトからのデータ取得など)をバックグラウンドで実行し、その結果を後から受け取るような処理のことを指す。

PromiseはJavaScriptのオブジェクトであり、非同期処理の最終的な完了(または失敗)およびその結果の値を表す。

let promise = new Promise((resolve, reject) => {
    // 非同期処理
    if (/* 処理が成功したら */) {
        resolve('Success!');
    } else {
        reject('Failure!');
    }
});

非同期処理が成功すればresolveを呼び出し、失敗すればrejectを呼び出す!

Promiseは、主に3つの状態を持つ!

  • pending(保留中):非同期処理がまだ完了していない状態
  • fulfilled(完了):非同期処理が成功して完了した状態
  • rejected(拒否):非同期処理が失敗した状態

チェーンとは?

Promiseの最大の特徴の一つは、.then()メソッドや.catch()メソッドを使って、連続した処理を「チェーン」のようにつなげることができる点!これを「チェーン」と呼ぶ。

例:

fetch('URL')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log("エラーが発生しました: " + error);
  });
  1. fetch('URL')でデータを取得。
  2. .then(response => response.json())で取得したデータをJSON形式に変換。
  3. 次の.then(data => {...}でJSONデータを処理。
  4. .catch(error => {...}でエラーが発生した場合の処理を行う。

このように、.thenや.catchを使って、連続した操作を順番に行うことができる。
これを「チェーン」と言う!

ちなみに、fetchは非同期処理を行う関数の一つ。
この関数がPromiseを返すために、.thenや.catchを使ってチェーンすることができる。

fetch、then、catchはすべてPromiseベースの処理の一部。

sayasaya

fetchについて

fetchはブラウザに組み込まれたAPIで、非同期にリソースを取得するためのもの。
fetchはPromiseを返すので、.thenメソッドをチェーンして処理を記述することができる!

fetch('URL')
  .then(response => response.json()) // 例としてJSONデータを取得する場合
  .then(data => {
    // 取得したデータの処理を記述
  })
  .catch(error => {
    // エラー処理
  });

上記は、指定したURLからJSONデータを取得する場合の基本的な構文。
fetchは他のオプションやヘッダーの指定、POSTリクエストの作成など、さまざまな拡張が可能🙆🏻‍♀️

sayasaya

idとclassがある理由は?

idとclassは、HTMLの要素を識別や選択するための属性であり、特定の目的のためにそれぞれが提供されている。

id属性の特性

一意性:一つのHTML文書内で、同じid属性値を持つ要素は1つだけであるべき。これにより、特定の要素を一
意的に識別することができる。

JavaScriptとの連携:JavaScriptで特定の要素を取得する際、getElementByIdメソッドなどを使用してid属性値を指定することで直接要素を参照することができる。

ページ内リンク:id属性を利用して、ページ内の特定の位置へのリンクを作成することができる。
例:

<a href="#section1">Go to Section 1</a><div id="section1">...<div>

class属性の特性

再利用性:一つのHTML文書内で、同じclass属性値を複数の要素に適用することができる。これにより、同じスタイルや動作を複数の要素に再利用することができる。

複数のクラス:一つの要素に複数のclass属性値をスペースで区切って指定することができる。これにより、複数のスタイルを組み合わせて適用することができる。
例:

<div class="highlight large-text">...</div>

CSSとの連携:スタイルシート(CSS)で特定のスタイルを適用する際、クラスセレクタを使用してclass属性値を指定することで、該当する要素にスタイルを適用することができる。

なぜ両方が存在するのか?

idは、特定の要素を一意的に識別するためのもの。
一方、classは一般的なスタイルや動作を複数の要素に適用するためのもの。

これにより、Webページのデザインや動作を効率的に制御することができる。

簡単に言うと、idは「このHTML文書内で唯一のもの」として要素を特定するのに使用。
classは「これらの要素は何らかの共通点がある」としてグルーピングするのに使用する。

sayasaya

NodeList

NodeListは、DOMノードのコレクションやリストを表すオブジェクト。
多くの場合、querySelectorAllメソッドを使用してDOM要素を選択すると、返されるのはNodeList。

例:

const divs = document.querySelectorAll('div'); // div要素すべてを選択
console.log(divs instanceof NodeList); // true

NodeListは、配列のようにインデックスを使ってアクセスできるが、配列のメソッド(例:map, filter, reduce)は直接使用できない。

ただし、forEachはNodeListで直接使用することができる。

const topSections = document.querySelectorAll('.top-section');
console.log(topSections);

topSections.forEach((topSection) => {
  topSection.addEventListener('click', function () {
    this.nextElementSibling.classList.toggle('active');
    this.children[1].classList.toggle('rotate');
  });
});

// topSections = .top-sectionが3つ入っている配列風オブジェクト(NodeList)
// forEach = 配列風オブジェクト(NodeList)の要素を1つずつ取り出す
// topSection = forEachで、定数topSectionsから取り出されたいずれかの.topSectionの要素

console.log

sayasaya

classList.toggleメソッド

指定されたクラスが要素に存在するかどうかをチェックし、存在していればそのクラスを削除し、存在していなければそのクラスを追加する機能を持っている。

これを使うことで、クラスの存在確認と追加・削除の2つの動作を1つのメソッドで行うことができるので、非常に便利!!

classList

DOM要素のクラス属性の読み取りや変更を容易にするプロパティ。

toggleメソッド

特定のクラス名を持つ要素があるかどうかをチェックし、クラスがあればそれを削除し、なければ追加する。

例:

要素が下記の場合、

<div class="example"></div>

実行すると、

classList.toggle('rotate')

要素は

<div class="example rotate"></div>

になる。

要素が再びクリックされ、

classList.toggle('rotate')

が再度実行されると、rotateクラスが削除され、要素は元の

<div class="example"></div>

に戻る。

この機能は、特定の状態をトグルする場面(例:メニューの開閉、ボタンのアクティブ/非アクティブ状態など)で非常に便利!!

sayasaya

HTMLCollectionとは?

HTML要素の集合を表すオブジェクトで、DOM (Document Object Model) において特定の方法で得られる一連の要素を表現する。

例えば、document.getElementsByTagName()メソッドや要素のchildrenプロパティを使用すると、HTMLCollectionが返される!

HTMLCollectionの特徴や注意点

動的なコレクション: HTMLCollectionは動的!
これは、DOM上で元の要素の集合が変更された場合、HTMLCollectionも自動的に更新されることを意味する。

配列とは異なる:HTMLCollectionは配列ではない。
そのため、通常の配列メソッド(例: forEachやmap)は直接使用できない。ただし、配列に変換する方法(例: スプレッド構文を使用する)がある。

インデックスアクセス:HTMLCollection内の要素は、0から始まるインデックスでアクセスできる。

名前付きアクセス:名前(name属性)やIDを持つ要素は、その名前やIDを使用して直接アクセスできる。ただし、これは古い方法であり、現代のコーディング標準ではあまり推奨されていない。

const divs = document.getElementsByTagName("div");

// 最初の<div>要素にアクセス
let firstDiv = divs[0];

// idが"example"の要素にアクセス (推奨されない方法)
let exampleDiv = divs.example; 

NodeListとHTMLCollectionの違いに注意!

両方とも要素のコレクションを表すが、
特に、NodeListはquerySelectorAllメソッドによって返され、通常は静的なコレクション。
(ただし、childNodesプロパティによって返されるNodeListは動的)

sayasaya

イベントリスナーとは

イベントリスナーは、非常に簡単に言うと、特定の「イベント」が発生したときに動作する関数や命令のセットのことを指す。

JavaScriptにおいて、Webページ上の要素に対して様々なイベント(クリック、キー入力、マウスオーバーなど)が発生することを検知し、それに応じて何らかのアクションを実行する際に使用される。

例:
ボタンのクリックイベント

  1. Webページ上のボタンをクリック。
  2. このボタンクリックは「イベント」としてブラウザに認識される。
  3. あらかじめ設定されていた「イベントリスナー」が、このクリックイベントを検知する。
  4. イベントリスナーに関連付けられた関数やコードが実行される(例: ダイアログが表示される、新しいページに遷移するなど)
js
// ボタンを参照
const buttonElement = document.querySelector("button");

// ボタンにクリックイベントのリスナーを設定
buttonElement.addEventListener("click", function() {
    alert("ボタンがクリックされました!");
});

このコードでは、ボタンがクリックされるとalert関数が実行され、ダイアログが表示されるという動作を示している。

このように、イベントリスナーを使うことで、ユーザーのアクションやブラウザの状態変化など、さまざまなイベントに反応してプログラムを動作させることができる!

イベントハンドラーとは

イベントハンドラーは、特定のイベント(クリック、キーの押下、マウスの移動など)が発生したときに実行される関数のことを指す。ユーザーが何かアクションを起こしたときや、特定の状況下で何かを自動的に実行したい場合に使用する。

例:

html
<button id="myButton">クリックしてください</button>
js
// ボタン要素を取得
const button = document.getElementById('myButton');

// ボタンがクリックされたときに実行する関数(イベントハンドラー)を定義
button.addEventListener('click', function() {
  alert('ボタンがクリックされました!');
});

このコードのfunction()部分がイベントハンドラー。
この関数は、myButtonというIDを持つボタンがクリックされたときに自動的に実行される。

イベントハンドラーの設定方法

イベントハンドラーは主に2つの方法で設定できる!

  • 属性としての設定:
    HTML要素の属性として直接イベントハンドラーを設定する方法。
    例: <button onclick="myFunction()">クリック</button>

  • addEventListenerを使用:
    JavaScriptでaddEventListenerメソッドを使用してイベントハンドラーを設定する方法。
    この方法が推奨されることが多い。

イベントハンドラーを使用することで、ユーザーとの対話や動的なコンテンツの変更など、ウェブページをよりインタラクティブにすることができる。

ユーザーが行ったアクションに応じて、ページの一部を更新したり、新しい情報を表示したり、データをサーバーに送信したりすることが可能になる。

イベントハンドラーはウェブページを動的にし、ユーザーとの対話を可能にするための重要なツール!

sayasaya

scroll

const contentContainers = document.querySelectorAll('.content-container');
//document.querySelectorAll('.content-container') = 指定したhtml要素をすべて返す
console.log('contentContainers', contentContainers);

window.addEventListener('scroll', function () {
  // ブラウザがスクロールされた場合
  contentContainers.forEach(function (value) {
    // .content-containerのhtml要素を1つずつ取り出す
    if (
      window.scrollY >
      value.getBoundingClientRect().top +
        250 +
        window.scrollY -
        window.innerHeight
    ) {
      // 画面の高さより、いずれかの.content-containerの相対位置が下回った場合
      value.classList.add('active');
    } else {
      // 画面の高さより、いずれかのcontent-containerの相対位置が上回った場合
      value.classList.remove('active');
    }
  });
});

このコードの目的は、ブラウザがスクロールされた際に特定のHTML要素(ここでは.content-container要素)がビューポートの特定の位置に来た時に、その要素にactiveというクラスを追加または削除すること。

コードの中の計算について

window.scrollY: これはページの最上部から現在のスクロール位置までの距離

value.getBoundingClientRect().top: これは.content-containerの要素の上端がビューポートの上端からどれだけ離れているか

window.innerHeight: これはビューポートの高さ(画面の表示領域)

計算のロジック

value.getBoundingClientRect().top + 250: .content-containerの上端から250px下の位置

window.scrollY - window.innerHeight: 現在のスクロール位置からビューポートの高さを引くことで、ビューポートの上端の位置を得る。

したがって、以下の条件

window.scrollY > value.getBoundingClientRect().top + 250 + window.scrollY - window.innerHeight

この条件は、.content-containerの上端から250px下の位置が、ビューポートの下端を超えた場合にtrueになる。

言い換えれば、.content-containerの上端から250px下がビューポートの下に移動した時、その要素にactiveクラスが追加される。

逆に、その条件を満たさない時(ビューポートの上にある時)は、activeクラスが削除される。

このようなロジックは、特定の要素が画面内に入ってきた(または出ていった)時にアニメーションや特定のスタイルを適用するためによく使われる!