03. Web制作に必要なJavaScript基礎

この章では、Web制作でJavaScriptを書くために必要な基礎文法を学びます。

JavaScriptにはたくさんの文法がありますが、最初からすべてを覚える必要はありません。Web制作でよく使うのは、HTML要素を取得し、状態を判断し、クラスや属性を切り替えるための文法です。

この章では、後の章でハンバーガーメニュー、アコーディオン、タブ、フォームなどを作る時に必要になるものに絞って解説します。

変数

変数は、値に名前を付けて使い回すためのものです。

Web制作では、取得したHTML要素、CSSクラス名、状態、設定値などを変数に入れて使います。

変数の例
const button = document.querySelector(".js-menu-button");
const menu = document.querySelector(".js-menu");
const activeClass = "is-active";

上のコードでは、3つの値に名前を付けています。

  • button: メニューボタン
  • menu: 開閉するメニュー
  • activeClass: 状態を表すCSSクラス名

変数を使うと、同じ値を何度も書かなくて済みます。また、「この値は何のためのものか」が読みやすくなります。

constとlet

現代のJavaScriptでは、基本的にconstletを使います。

書き方再代入主な使いどころ
constできない後から別の値に入れ替えないもの
letできる処理の途中で値を更新するもの
varできる古い書き方。新しく書く時は基本使わない

基本はconstを使い、後から値を入れ替える必要がある時だけletを使います。

constを使う例
const button = document.querySelector(".js-button");
const activeClass = "is-active";

取得した要素やクラス名は、後から別の値に入れ替えることが少ないのでconstで問題ありません。

letを使う例
let currentIndex = 0;

currentIndex = currentIndex + 1;

スライダーの現在位置や、スクロール前の位置など、処理の途中で値を更新するものはletを使います。

varを使わない理由

古い記事や既存案件のコードでは、varを見かけることがあります。

古い書き方
var button = document.querySelector(".js-button");

varは昔からある書き方ですが、今から新しく書くなら基本的に使いません。

理由は、constletの方が「この変数は後から変わるのか」がわかりやすく、意図しない上書きも減らしやすいからです。

命名の考え方

変数名は、短ければよいわけではありません。

あとから読んだ時に何を表しているかわかる名前にします。

読みにくい例
const b = document.querySelector(".js-button");
const m = document.querySelector(".js-menu");

このコードは短いですが、bmだけでは意味が伝わりにくいです。

読みやすい例
const menuButton = document.querySelector(".js-menu-button");
const globalMenu = document.querySelector(".js-global-menu");

Web制作では、HTMLやCSSのクラス名と対応する名前にしておくと読みやすくなります。

データ型

JavaScriptの値には種類があります。

Web制作でよく使うものを押さえておきましょう。

種類よく使う場面
文字列"is-active"クラス名、メッセージ、属性値
数値100スクロール量、インデックス、時間
真偽値truefalse開いているか、有効か、表示するか
配列["top", "about"]複数の値をまとめる
オブジェクト{ duration: 300 }設定値をまとめる
nullnull値が存在しないことを明示する
undefinedundefined値がまだ入っていない状態

文字列

文字列は、テキストの値です。

クラス名、ボタン文言、エラーメッセージ、属性値などで使います。

文字列
const activeClass = "is-active";
const errorMessage = "メールアドレスを入力してください。";

button.textContent = "閉じる";

文字列は"または'で囲みます。この教材では、コード例では主に"を使います。

変数を文字列の中に埋め込みたい時は、テンプレートリテラルを使います。

テンプレートリテラル
const itemCount = 3;
const message = `選択中の項目は${itemCount}件です。`;

テンプレートリテラルでは、バッククォートで囲み、${}の中に変数を書けます。

数値

数値は、スクロール量、表示位置、配列の番号、タイマー時間などで使います。

数値
const headerHeight = 80;
const animationDuration = 300;
let currentIndex = 0;

CSSのpxなどの単位は、JavaScriptでは文字列として扱うこともあります。

単位付きの値
const headerHeight = 80;

target.style.scrollMarginTop = `${headerHeight}px`;

数値のまま計算し、CSSへ渡す時にpxを付ける、という流れがよくあります。

真偽値

真偽値は、trueまたはfalseのどちらかです。

Web制作では「開いているか」「エラーがあるか」「送信できるか」のような状態を表す時に使います。

真偽値
const isOpen = menu.classList.contains("is-active");
const isRequired = input.required;
const isValid = input.value !== "";

変数名は、ishascanなどで始めると、真偽値だとわかりやすくなります。

状態が伝わる名前
const isOpen = true;
const hasError = false;
const canSubmit = true;

配列

配列は、複数の値を順番にまとめるためのものです。

配列
const menuItems = ["トップ", "サービス", "お問い合わせ"];

Web制作では、複数のHTML要素をまとめて扱う時によく似た考え方を使います。

複数の要素を取得する
const accordionButtons = document.querySelectorAll(".js-accordion-button");

accordionButtons.forEach((button) => {
    button.addEventListener("click", () => {
        button.classList.toggle("is-active");
    });
});

querySelectorAllで取得したものは厳密には配列ではなくNodeListですが、forEachで繰り返し処理できます。

この違いは後のDOM操作の章で詳しく扱います。

オブジェクト

オブジェクトは、名前付きの値をまとめるためのものです。

オブジェクト
const user = {
    name: "山田",
    age: 28,
    isMember: true,
};

Web制作では、ライブラリの設定値や、自作UIの設定をまとめる時によく使います。

設定値をまとめる
const sliderOptions = {
    type: "loop",
    perPage: 3,
    gap: "24px",
    autoplay: true,
};

SplideやGSAPなどのドキュメントでは、このようなオブジェクト形式の設定がよく出てきます。

nullとundefined

nullundefinedは、どちらも「値がない」状態に関係します。

ざっくり分けると、次のように考えるとわかりやすいです。

意味
null意図的に「何もない」としている
undefined値がまだ入っていない、または見つからない

Web制作でよく見るのは、要素が見つからなかった時のnullです。

要素が見つからない例
const button = document.querySelector(".js-button");

console.log(button);
// 対象要素がなければ null

この状態でいきなりイベントを付けようとするとエラーになります。

エラーになる例
const button = document.querySelector(".js-button");

button.addEventListener("click", () => {
    console.log("クリックされました");
});

対象要素が存在するか確認してから処理します。

ガード処理
const button = document.querySelector(".js-button");

if (button) {
    button.addEventListener("click", () => {
        console.log("クリックされました");
    });
}

条件分岐

条件分岐は、「もしAならこの処理、そうでなければ別の処理」という書き方です。

if文
const isOpen = menu.classList.contains("is-active");

if (isOpen) {
    menu.classList.remove("is-active");
} else {
    menu.classList.add("is-active");
}

Web制作では、状態に応じて処理を分ける時によく使います。

  • メニューが開いているなら閉じる
  • 入力欄が空ならエラーを出す
  • スクロール量が一定以上ならヘッダーを変える
  • 画面幅がスマホなら処理を変える

比較演算子

条件を書く時は、比較演算子を使います。

書き方意味
===等しい
!==等しくない
>より大きい
<より小さい
>=以上
<=以下
比較
const scrollY = window.scrollY;

if (scrollY > 100) {
    header.classList.add("is-scrolled");
}

基本的には、等しいかどうかの比較では===を使います。

複数条件

複数の条件を組み合わせる時は、&&||!を使います。

書き方意味
&&かつ
||または
!ではない、反転する
かつ
if (input.value !== "" && checkbox.checked) {
    submitButton.disabled = false;
}
または
if (input.value === "" || !checkbox.checked) {
    submitButton.disabled = true;
}

!は真偽値を反転します。

反転
const isOpen = button.getAttribute("aria-expanded") === "true";

button.setAttribute("aria-expanded", String(!isOpen));

開いているなら閉じる、閉じているなら開く、という切り替え処理でよく使います。

truthyとfalsy

JavaScriptでは、truefalseそのものではなくても、条件式の中で真偽値のように扱われる値があります。

たとえば、document.querySelectorで要素が見つかれば条件は真として扱われ、見つからずnullなら偽として扱われます。

要素の有無を判定する
const modal = document.querySelector(".js-modal");

if (modal) {
    modal.hidden = false;
}

この書き方は実務でとてもよく使います。

関数

関数は、処理に名前を付けてまとめるためのものです。

関数
function openMenu() {
    menu.classList.add("is-active");
    button.setAttribute("aria-expanded", "true");
}

関数にすると、同じ処理を何度も書かなくて済みます。また、コードの意図が読みやすくなります。

関数を呼び出す
openMenu();

Web制作では、UIごとに初期化関数を作ることがよくあります。

初期化関数
function initMenu() {
    const button = document.querySelector(".js-menu-button");
    const menu = document.querySelector(".js-menu");

    if (!button || !menu) {
        return;
    }

    button.addEventListener("click", () => {
        menu.classList.toggle("is-active");
    });
}

initMenu();

returnは、関数の処理をそこで終わらせるためにも使えます。

早期return
if (!button || !menu) {
    return;
}

この書き方は、対象要素がない時のガード処理でよく使います。

関数宣言とアロー関数

関数にはいくつか書き方があります。

関数宣言
function closeMenu() {
    menu.classList.remove("is-active");
}
アロー関数
const closeMenu = () => {
    menu.classList.remove("is-active");
};

どちらも関数です。

この教材では、処理に名前を付けて外から呼びたいものはfunction、イベントの中に書く短い処理はアロー関数を使うことが多いです。

イベント内のアロー関数
button.addEventListener("click", () => {
    menu.classList.toggle("is-active");
});

最初は書き方の違いを完璧に説明できなくても大丈夫です。まずは「処理をまとめるもの」として読めるようになりましょう。

引数

引数は、関数に外から渡す値です。

引数
function showMessage(message) {
    console.log(message);
}

showMessage("送信が完了しました。");
showMessage("入力内容を確認してください。");

同じ関数でも、渡す値によって動きを変えられます。

Web制作では、要素を引数で渡すと使い回しやすくなります。

要素を渡す
function openPanel(panel) {
    panel.hidden = false;
    panel.classList.add("is-active");
}

このようにすると、複数のパネルに対して同じ処理を使えます。

戻り値

戻り値は、関数の処理結果として返す値です。

戻り値
function isEmpty(input) {
    return input.value === "";
}

if (isEmpty(nameInput)) {
    console.log("名前を入力してください。");
}

フォームの入力チェックでは、判定だけを関数に分けると読みやすくなります。

メールアドレスの簡易チェック
function isEmail(value) {
    return value.includes("@");
}

配列とループ

複数の要素に同じ処理をしたい時は、繰り返し処理を使います。

Web制作では、forEachをよく使います。

複数ボタンにイベントを付ける
const buttons = document.querySelectorAll(".js-modal-open");

buttons.forEach((button) => {
    button.addEventListener("click", () => {
        console.log("モーダルを開く");
    });
});

1つのボタンだけならquerySelectorで足りますが、同じボタンが複数あるならquerySelectorAllforEachを使います。

mapとfilter

mapfilterは、配列から新しい配列を作る時によく使います。

map
const prices = [1000, 2000, 3000];
const pricesWithTax = prices.map((price) => {
    return price * 1.1;
});
filter
const items = [
    { name: "サービスA", isVisible: true },
    { name: "サービスB", isVisible: false },
    { name: "サービスC", isVisible: true },
];

const visibleItems = items.filter((item) => {
    return item.isVisible;
});

Web制作の定番UIだけならforEachの出番が多いですが、カード一覧、絞り込みUI、検索結果の表示などではmapfilterも使います。

最初は、次のように覚えておけば十分です。

メソッド役割
forEach1つずつ処理する
map1つずつ変換して新しい配列を作る
filter条件に合うものだけを残す

オブジェクトで設定を持つ

Web制作のJavaScriptでは、設定値をオブジェクトでまとめると読みやすくなることがあります。

設定をまとめる
const options = {
    activeClass: "is-active",
    duration: 300,
    closeOnEscape: true,
};

小さな実装ではここまでしなくてもよいですが、複数の値をまとめたい時には便利です。

ライブラリでも同じ考え方が出てきます。

Splideの設定例
const splide = new Splide(".splide", {
    type: "loop",
    perPage: 3,
    gap: "24px",
    breakpoints: {
        768: {
            perPage: 1,
        },
    },
});

splide.mount();

この章でオブジェクトの形に慣れておくと、ライブラリの章でかなり楽になります。

よくある失敗

基礎文法の段階でよくある失敗を整理しておきます。

  • constで宣言した変数に再代入しようとしてエラーになる
  • 要素が見つからずnullなのに、イベントを付けようとしてエラーになる
  • ====を間違える
  • 文字列なのにクォートで囲み忘れる
  • 複数要素があるのにquerySelectorで最初の1つだけ取得してしまう
  • 関数を作っただけで、呼び出していない
  • returnした後に書いた処理が実行されないことに気づかない

エラーが出た時は、まずConsoleのエラー文を読み、どの行で止まっているか確認します。

エラー解決は後の章で詳しく扱いますが、最初から「エラーは読むもの」と思っておくと、苦手意識が減ります。

この章のまとめ

この章では、Web制作でよく使うJavaScriptの基礎文法を学びました。

  • 基本はconst、値を入れ替える必要がある時だけletを使う
  • 変数名は、後から読んで意味がわかる名前にする
  • 文字列、数値、真偽値、配列、オブジェクトはWeb制作でも頻繁に使う
  • 条件分岐では、状態や入力内容に応じて処理を分ける
  • 関数に処理をまとめると、読みやすく使い回しやすくなる
  • 複数要素にはquerySelectorAllforEachを使う場面が多い
  • 対象要素がない時にエラーにならないよう、ガード処理を書く

次の章では、JavaScriptからHTML要素を取得し、クラスや属性を変更するDOM操作を学びます。