こんにちは。
タイトル通り、本日から「JavaScript基礎習得メモ ~27歳・未経験からWeb系転職を目指して~」を書いていきます。
経緯としては、かれこれ2年ほど、現職と平行し Web制作会社への転職を目指して、あっちこっちスキルに手を付けたり、ポートフォリオサイトをいくつか制作しましたが、やってみたいという強い思いとは裏腹、一向に'コードを書くこと'への苦手意識が消えず...。
そろそろ焦らないとまずいと思い、'フロントエンド'の方向に進みたいという前提で、MENTAにてプロの方へアドバイスを募ったところ、
「JavaScriptは一生稼げる1番の友達」
「React→Next.jsは現場全員が使っている超必修スキル」
との名言をいただきまして。モチベーションアップにつながりました。
今後の学習方法としては、
・ドットインストールのJavaScript動画を片っ端から見直し、出来る限り詳細に、どこが分かる/分からないを整理する(分からなくてもとりあえずメモ)。
・ドットインストール公式様が出しているnote記事「JavaScriptに挫折しそうな方への提案 〜 自分で書けるようになるまで」(以下URL)を参考にする。
...といった要領で進めていこうと思います。
https://note.com/dotinstall/n/n9e2c2eedc096
はじめに。注意。
偶然この記事にたどり着いた方、ごめんなさい。本当に拙いです。初歩の初歩状態です。間違っているところもあるかもしれません。勉強しながら継続して編集していきます。
はじめてのJavaScript(全7回)
- jQueryやBootstrapとは違い、自分の欲しい機能をとことんカスタマイズできるようになる。Node.js、Reactに展開可能
- タブメニューや計算ツールなど、細部までコードには触れないが、出来ることがたくさんあることが分かる序章
- 多少分からないことがあっても、先に進むべし
JavaScript入門 基礎文法編(全27回)
- ライブラリやフレームワークへ進む前に、基本的な文法をしっかりと確認しておくこと
-
alert(メッセージ);
、console.log(メッセージ);
→シンプル。不明点は特になし - 演算:
console.log(10 ** 3);
= 1000→べき乗。知らなかったので覚えておく
-
const
→定数の宣言に使われる(消費税の計算など)。=
で代入 - あとで値を再代入したい場合は
let
=「変数」で宣言する - 値が途中で変わっていたりするとコードが読みづらいため、基本的には
const
で宣言し、仕方ない時だけlet
にする。(var
は古いので使わない) -
値を変えないものは
const
、値を変える必要があるならlet
-
${...}
定数や変数を埋め込む(「テンプレートリテラル」という) - 「~と等しい」は
===
、「~と等しくない」は!==
を使う('='の数に注意) -
if (条件) {出力} else if (条件) {出力} else (条件) {出力}
お馴染みの条件分岐 -
右クリック→「ドキュメントのフォーマット」でインデントを綺麗に整理できる。(初耳でした。汗)
- スコアなど数値でなく、値が定まっている文字列で条件分岐させる場合は、
switch
を使う。switch (...) {case '...': console.log('...'); break; default: console.log('...'); break;}
-
for
:反復処理。条件を満たしてる段階まで処理を繰り返す。例:for (let price = 150; price <= 160; price++)
-
do...while
:最低1回は必ず処理を実行し、その後while
の条件を評価してループ継続するか判断する構文。例:ユーザー入力によるメニュー選択など、「最初に一度は案内を出したい」時('1~3からメニューを選んでくださいなどの状況')に使う
let command;
do {
command = Number(prompt('Menu 1, 2, 3 or 0 to exit'));
// do=初期メッセージとして必ず1度は表示させる
if (command === 0) {
console.log('終了します');
// 0を押すことで卓上メニュー端末の動作を終了
} else {
console.log(`メニュー${command}を処理中...`);
// お客様が1~3の中で食べたいものを選択中
}
} while (command !== 0);
// while:command が 0 でない限り、do の処理を繰り返す
// → 「0以外の数字(1~3)が入力されたらメニュー処理を継続」
// do...while文:最初の1回は必ず実行されるループ
// ユーザーにメニュー番号を入力させ、0が入力されるまで繰り返す
-
if
、for
、while
、do...while
の違い:-
if
:条件が「1回だけ」真かどうかを判断して、そのときだけ処理を実行する。→ 「ある条件のときに一度だけ処理したい」ときに使う
例:if (score > 80) { console.log('よくできました'); }
-
for
: 最初から「何回繰り返すか」が分かっているときに使う
例:150〜160円の値段で繰り返す→for (let price = 150; price <= 160; price++) { console.log("Price: " + price); }
-
while
:条件が「真の間、何度も繰り返し」処理を実行する。→ 「条件を満たす間、何度も処理を続けたい」ときに使う
例:let count = 0; while (count < 3) { console.log('処理中...'); count++;}
-
do...while
:条件に関係なく、まず1回だけ実行し、その後で条件を判定して繰り返す。→ 「とにかく1回は処理を実行したい、その後も条件次第で繰り返したい」ときに使う
例:ユーザーへ何度も入力を求めたいが、必ず最初に1回は聞く必要があるとき→let command; do { command = Number(prompt('Menu 1, 2, 3 or 0 to exit')); console.log(
メニュー${command}を処理中...); } while (command !== 0);
☆使い分け:よく使われるfor
を試してみて、うまくいかなかったらwhile
、それでもうまくいかなかったらdo...while
という使い分けで書いてみる
-
-
break
:反復処理全体から抜けるための命令 -
continue
:反復処理の途中でそれ以降の処理をスキップして、次の反復処理に移るための命令
-
if
を使うまでもない短い条件の場合は、三項演算子?
を使う
例:score < 30 ? 'Team A' : 'Team B'
は、score が30より小さいなら'Team A'、そうでなければ 'Team B'となり、scoreが40の場合、30未満ではない=false='Team B'が出力される。※複雑な条件や処理にはif
/else
を使うこと
-
論理演算子
&&
:なおかつ||
:または - スコープ:定数や変数の参照可能な範囲 → JavaScriptでは主に「グローバルスコープ」「ローカルスコープ」の2つがある
'use strict';
let x = 10;
{
let x = 20;
console.log(x);
}
// {}内はローカルスコープと呼ばれる。出力は20。
console.log(x);
// {}外はグローバルスコープと呼ばれる。出力は10。
※別のjsファイルでxを使いたい際にローカルスコープを使用する。
- 基礎文法編まとめ(感想)
関数などが出てきていないため、'本番っぽいコード'ではないものの、大切な基礎が詰まっていた。for
、while
、do...while
や、if
/else
と三項演算子?
の使い分けが難しく感じたが、こうした基礎が頭に入っていて、必要な時に思い出して使えるのが'書ける'という状態なのだなと感じた。
JavaScript入門 関数編(全12回)
- 関数は
return
を使って結果を返す。return
を省略すると、返り値はundefined
になる。console.log()
は「表示」するだけで、値を返していない。他の関数や処理で再利用したい場合は、必ずreturn
で返すこと
function sum(a, b) {
return a + b;
}
console.log(sum(3, 7) * 2); // → 20
- 引数のデフォルト値:関数に初期値を設定することで、引数が省略された場合にも安全に処理を行える。消費税率や送料など、オプション的な値を関数内で処理したいときに使う
'use strict';
{
function calculateTotal(price, amount, rate = 1.1) {
return price * amount * rate;
}
console.log(calculateTotal(100, 10)); // → 1100(rateは1.1)
console.log(calculateTotal(150, 10)); // → 1650(rateは1.1)
console.log(calculateTotal(200, 10)); // → 2200(rateは1.1)
console.log(calculateTotal(120, 10, 1.08)); // → 1296(rateを上書き)
}
-
早期リターン:条件に合えばすぐ
return
して、それ以降の処理をスキップする書き方。if
~return
で無駄な処理を省いてコードをスッキリ書ける
'use strict';
{
function calcurateTotal(price, amount, rate = 1.1) {
// 早期リターン実装前
// if (amount >= 100) {
// return price * amount;
// } else {
// return price * amount * rate;
// }
if (amount >= 100) {
// 早期リターン
return price * amount;
}
return price * amount * rate;
}
console.log(calcurateTotal(100, 100));
console.log(calcurateTotal(1000, 10));
- 引数のスコープ:JavaScriptでは、関数の引数や中で定義した変数は、その関数の中(スコープ)でしか使えず、関数の外で同じ名前を使おうとすると、エラーになる
'use strict';
{ // ←この{}は「スコープブロック」と言って関数ではないので注意!=外!
function double(num) {
// ← 「中!」:この中だけで num は使える
return num * 2;
}
function triple(num) {
return num * 3; // ← ここも「中!」だから num は使える
}
console.log(double(10)); // → 20
// ↓↓↓ 「外!」で num を使おうとするとエラー!
// console.log(num); // エラー:num is not defined
console.log(triple(20)); // → 60
}
- 実践すべき技:同じ処理を関数にまとめることで、コードの重複を減らし、保守性も高くなる
'use strict';
{
function showAd() {
console.log("---------");
console.log("SALE! 50% OFF!");
console.log("---------");
}
function showContent() {
console.log("BREAKING NEWS!");
console.log("Two baby pandas born at our Zoo!");
}
showAd(); // 同じ広告表示を関数で共通化!
showContent();
showAd();
}
-
関数宣言と関数式:JavaScriptでは、関数を「関数宣言」と「関数式」という2つの方法で定義できる
まず 「関数宣言」 は、関数を先に呼び出しても動作する。これは「ホイスティング」という、コードのどこに宣言を書いても実行時には、コードの先頭へ書いたことになる仕組み(=関数の巻き上げ)があるため。 - 一方 「関数式」 は、関数を変数に代入する形で定義する。こちらは通常の変数と同じ扱いになるため、定義より前に呼び出すとエラーになる
// 関数宣言:先に呼び出してもOK
'use strict';
{
console.log(double(5)); // 呼び出しOK!
function double(num) {
return num * 2;
}
}
※function double(num)
のような 関数宣言は、定義より前に呼び出してもエラーにならない。
// 関数式:先に呼ぶとエラー!
'use strict';
{
console.log(double(5)); // エラー!double is not defined
const double = function(num) {
return num * 2;
};
}
このように、関数式(const
に代入する形)で定義された関数は、定義の前に呼び出すとエラーになる。
- 最初は「関数宣言」を使うと安心
- 「関数式」はアロー関数などとセットでよく使われる+“定義してから使う”が鉄則!
// 安心して使える関数宣言(初心者にやさしい)
function greet(name) {
return `Hello, ${name}`;
}
console.log(greet("Alice"));
// 実務ではこちらが主流(アロー関数+関数式)
const greet = (name) => `Hello, ${name}`;
console.log(greet("Bob"));
//どちらも書けるようにしておく!!
- 重要!:関数を引数に渡す「コールバック関数」
- 「関数を引数に渡す」とは?
関数の中で、別の関数を実行したい時に、引数として関数を渡すテクニック。「何をどう処理するか」を あとから決めたいときに便利!
// コールバック関数:関数を引数に渡すことで、あとから処理内容を柔軟に決められる
const calc = (num, func) => {
return func(num);
};
console.log(calc(20, (n) => n * 2)); // => 40
- ※「コールバック関数」は関数の“用途”の分類
- ※「アロー関数」は関数の“書き方”の一種
☆ なぜ大事か?どこで使うか?
Web制作やJS実務で、以下のような場面で頻出。
用途 | 使われる場所の例 |
---|---|
イベント処理 | addEventListener("click", handler) |
配列の処理 |
arr.map(func) や forEach(func)
|
APIのレスポンス処理 | fetch().then(response => {...}) |
アニメーション制御 | setTimeout(() => {...}, 1000) |
-
Q.何が一番使うのか?
→ 場面によって違うが、確実に使う頻度が高いのはアロー関数 + コールバック関数の組み合わせ である!
この書き方は、React、jQuery、API操作、配列操作、アニメーション処理など、JS実務で“ほぼ確実に登場” する。
- 関数編まとめ(感想)
難しさは引き続き感じたが、見たことのあるコードが登場し、実務で'ここが特に使う'といったレベル感が整理できて良かった。あとから最も復習すべきセクションとなったかもしれない。
関数と構文を「合わせて使う」実務的な例
関数 ✕ if(条件によって処理を分けたい)
const greet = (name) => {
if (!name) {
return '名前がありません';
}
return `こんにちは、${name}さん`;
};
console.log(greet('太郎')); // => こんにちは、太郎さん
console.log(greet('')); // => 名前がありません
-
if
で条件分岐し、関数の中で動的に出力を変えてる例 - フォーム入力チェックなど実務でよくあるパターン!
関数 ✕ for(繰り返しの処理をまとめたい)
const printScores = (scores) => {
for (let i = 0; i < scores.length; i++) {
console.log(`${i + 1}人目の点数: ${scores[i]}`);
}
};
printScores([70, 80, 90]);
// => 1人目の点数: 70
// => 2人目の点数: 80
// => 3人目の点数: 90
-
for
のループ処理を関数にまとめることで、再利用性UP! - 配列の値を順番に処理する基本中の基本
関数 ✕ forEach(配列の要素を順に処理)
const showFruits = (arr) => {
arr.forEach((fruit, index) => {
console.log(`${index + 1}個目の果物:${fruit}`);
});
};
showFruits(['りんご', 'みかん', 'バナナ']);
// => 1個目の果物:りんご
// => 2個目の果物:みかん
// => 3個目の果物:バナナ
-
forEach
は関数(アロー関数)を中に入れて使う構文 - コールバック関数の練習にもなる!
JavaScript入門 データ構造編(全27回)
- 配列の基礎
'use strict';
{
const scores = [
70,
90,
80,
85,
// 値を追加することもあるので、最後の値はカンマがあってもいい。
];
console.log(scores[2]); //80
console.log(scores.length); //個数。出力結果は4。
scores[1] = 95;
console.log(scores); // [70, 95, 80, 85]
}
-
length
は要素の個数 を表す
-
const
の値を後から書き換えると通常はエラーになるが、配列の場合は例外で、後から書き換えが出来る。但しこの場合、const
以外を使うと上手くいかないため注意!
- 配列の末尾に要素を追加=
push
、配列の末尾の要素を削除=pop
- 配列の先頭に要素を追加=
unshift
、配列の先頭の要素を削除=shift
→push
はよく使う。それ以外は必要に応じて復習する
for
:配列の中身を順に取り出して処理する
'use strict';
{
const scores = [
70,
90,
80,
85,
];
scores.push(77, 88);
// 要素取得
// console.log(scores[0]);
// console.log(scores[1]);
// console.log(scores[2]);
// console.log(scores[3]);
// ↑ この意味を成すコードを、forで書く!
for (let i = 0; i < scores.length; i++) {
console.log(scores[i]);
}
// `.length`の部分 → 定着させるべきオススメの書き方
// (`i<4`とか書くよりも保守性が高い)
}
forEach
:途中にアロー関数を使う。for文よりもコード量が少なく、配列の処理パターンとして“暗記必須”の書き方
'use strict';
{
const scores = [
70,
90,
80,
85,
];
scores.forEach((score, index) => {
console.log(`${index}: ${score}`);
});
}
☆forEach
とfor
の使い分け
-
forEach
が向いている場面(9割以上のケース)- 商品一覧や画像ギャラリーなど、全てのデータを順番に表示する
- ボタンなど複数要素に一括でイベントを追加する
- ユーザー一覧やエラーメッセージなどを順にHTMLへ反映
-
処理を途中で止める必要がないとき(break不可)
-
for
が向いている場面(条件による制御が必要なとき)- 特定の条件でループを途中で止めたい(
break
したい) - 1個飛ばし・偶数番目だけ処理などの細かい制御が必要
-
逆順でループしたい(後ろから処理したい)
- 特定の条件でループを途中で止めたい(
- 「配列を順に処理する」とは?
- Web制作の実務で例えるなら:
- 画像や商品などの一覧UIを自動で生成する
- 全ボタンや要素にまとめてイベントをつける
- APIから取得したデータをページ上に並べる
- 複数のエラー文を一括で表示する
- まとめると⇒
- ほとんどの場面では
forEach
でOK! - UIパーツを複数処理するときは
forEach
! - 特殊な処理をしたいときだけ
for
!
- ほとんどの場面では
☆ forEach
のインデックス(i)を使ったミニクイズ解説
const nums = [3, 2, 8];
nums.forEach((num, i) => {
console.log(i * 3);
});
-
num
:配列の中の値(3, 2, 8) -
i
:インデックス(何番目の要素か → 0, 1, 2)
- 実行時の内容
i(インデックス) | num(値) | i * 3 | 出力される値 |
---|---|---|---|
0 | 3 | 0 | 0 |
1 | 2 | 3 | 3 |
2 | 8 | 6 | 6 |
-
forEach((値, インデックス) => {...})
の形を覚えておくと便利! - 値だけ使うなら
(num) => {...}
- インデックスも使いたいときは
(num, i) => {...}
※第2引数がインデックス(i)なのはforEach()
など配列用のメソッドの時だけ。
- 配列は
[]
(角括弧)だったが、オブジェクトでは{}
(波括弧)を使う - 値に名前をつけるには、それぞれの値の前に文字列を配置して、
:
で区切る。const scores = {math : 80, english : 90};
→これがオブジェクトのリテラル表現で、これで1つの値になるので、定数に代入できる。math
やenglish
の部分を「キー」、80
や90
の部分を「値」、「キー」「値」を合わせて「プロパティ」と呼ぶ。
- プロパティへのアクセス、代入、追加、削除の方法
'use strict';
{
const scores = {
math: 80,
english: 90,
};
console.log(scores.english); //プロパティへのアクセス
scores.math = 88; //プロパティへの代入(ドットで繋げる)
scores.physics = 70; //プロパティの追加(新しく'物理学'を追加)
delete scores.english; //プロパティの削除('delete'を使う)
console.log(scores);
// 結果:90(scores.english)
// math: 88
// physics: 70
}
- プロパティが増えた場合、配列の反復処理を使いたいところだが、オブジェクトに対して直接
forEach()
を使うことはできない → 一旦オブジェクトを配列に変換してからforEach()
を使うというテクニックがある
'use strict';
{
const scores = {
math: 80,
english: 90,
};
let sum = 0; // 合計を保持するための変数をsumで宣言し、0で初期化
scores.physics = 70; // 物理学を追加
// 今までのやり方:1つずつ取り出して表示(数が少ないとき)
// console.log(scores.math);
// console.log(scores.english);
// プロパティ(キーと値)が増えたら毎回書くのが大変!
// → Object.entries()で [キー, 値] の配列に変換し、forEachでまとめて処理
const entries = Object.entries(scores);
entries.forEach((prop) => {
// 【復習:アロー関数】元々は
// entries.forEach(function(prop) { のところを短く見やすく。
// (prop)=プロパティ=['math', 80],['english', 90],
sum += prop[1]; // 値(点数)を1つずつ足す → 合計にする
console.log(`${prop[0]}: ${prop[1]}`); // math: 80、english: 90で表示
//prop[0] → 'math'(キー)、prop[1] → 80(値)
});
console.log(`Sum: ${sum}`);
console.log(`Average: ${sum / entries.length}`);
// 毎回、合計と平均を表示(平均=合計 ÷ 科目数)
// 結果:math: 80、english: 90、physics: 70、Sum: 240、Average: 80
// 合計(Sum)と平均(Average)は、ループの外でまとめて表示する
// → forEachの中に書いてしまうと「途中経過」が毎回表示されてしまう!
// ex)1回目の合計、2回目の合計、…と何度も表示されてしまうため、
// 「最終結果」を見たいときはループを抜けたあとに表示する。
}
- 配列の先頭や末尾の要素を操作するには
push
、pop
、unshift
、shift
があったが、途中の要素を挿入・削除する場合これらは使えず、代わりにsplice()
を使う。splice(➀変化する位置のインデックス[0][1][2].., ➁削除する要素の数, ➂追加する要素1, ➃追加する要素2...);
'use strict';
{
const scores = [70, 90, 80, 85];
scores.splice(2, 0, 77, 88);
// splice(➀変化する位置のインデックス[0][1][2]..,
// ↑ 上記の場合、[2]なら80の前を指す。
// ➁削除する要素の数(0), ➂追加する要素1(77), ➃追加する要素2(78)...);
// [70, 90, 77, 88, 80, 85];
const deleted = scores.splice(3, 1);
// [70, 90, 77, 88, 80, 85];から開始。
// splice(➀変化する位置のインデックス[3] = 88,
// ➁削除する要素の数(1));
// [70, 90, 77, 80, 85];
// 削除された[88]が delited に代入される。
scores.splice(2, 2, 30);
// [70, 90, 77, 80, 85];から開始。
// splice(➀変化する位置のインデックス[2] = 77,
// ➁削除する要素の数(2) → 77, 80を指す。
// ➂追加する要素1(30));
// // [70, 90, 30, 85];
console.log(scores); // [70, 90, 30, 85]
console.log(deleted); // [88]
}
-
要素を「|」で区切って表示させたい時は、
join('|')
を使う。 カンマで区切って表示させたい時は、引数なしのjoin()
(=デフォルトでカンマ区切りになる)を使う。 区切らずに繋げたい時は、join('')
と書く - 逆に、文字列を配列にしたい場合は
split()
を使う(例:split('|')
)
'use strict';
{
// const names = ['Taro', 'Jiro', 'Saburo'];
// 要素を|で区切って表示させたい時
// console.log(names.join('|')); // Taro|Jiro|Saburo
// 要素をカンマで区切って表示させたい時
// console.log(names.join()); // Taro,Jiro,Saburo
// |でもカンマでも区切らず繋げたい時
// console.log(names.join('')); // TaroJiroSaburo
// 逆に文字列から配列を作りたい時
const names = 'Taro|Jiro|Saburo';
console.log(names.split('|')); // ['Taro', 'Jiro', 'Saburo']
}
-
配列の中身を1つずつ加工して「新しい配列」を作りたい時は
map()
を使う(加工の例:税込価格に変換、名前に「さん」を付ける など)
'use strict';
{
const prices = [100, 150, 200];
// // それぞれを10%の税込み価格にした配列を別途用意する
// const pricesWithTax = [];
// prices.forEach((price) => {
// pricesWithTax.push(price * 1.1);
// }); //上記を簡潔に書くためにmap()を使う
const pricesWithTax = prices.map((price) => {
return price * 1.1;
});
console.log(pricesWithTax);
// ある配列の各要素を処理して新しい配列を作る場合、
// map() のほうが簡潔に書けるのでこちらを好む人も多い
}
-
配列から「条件に合う要素だけ」を取り出して新しい配列を作りたい時は
filter()
を使う(例:150円以上の商品だけ、偶数だけ、指定文字列を含む要素だけ、など)
'use strict';
{
const prices = [100, 150, 200];
// 150円以上の価格だけを抽出し、これとは別の新しい配列を作りたい時
// const pricesOver150 = [];
// prices.forEach((price) => {
// if (price >= 150) {
// pricesOver150.push(price);
// }
// }); //上記を簡潔に書くためにfilter()を使う
const pricesOver150 = prices.filter((price) => {
return price >= 150; // 条件に合う要素だけを新しい配列に入れる
});
console.log(pricesOver150); // [150, 200]
}
-
map
→ 元の配列の各要素を処理して同じ要素数の配列を返す -
filter
→ 元の配列の値はそのままに条件に合致するものだけを抽出する
- 分割代入:配列の代入を短く書ける
'use strict';
{
const scores = [70, 90, 80, 85];
// これらの値をこの後のコードでよく使うことになったので、
// それぞれに分かりやすい定数名を付けたくなったとする。
// const first = scores[0];
// const second = scores[1];
// const third = scores[2];
// const fourth = scores[3];
// ↑これを一気にスッキリ書ける!!
const [first, second, third, fourth] = scores;
// 新しく配列を作るコードではない。これは分割代入!混同注意!
console.log(first);
console.log(second);
console.log(third);
console.log(fourth);
}
- 分割代入の値の入れ替え
'use strict';
{
let start = 'Tokyo';
let goal = 'Osaka';
// 【値を入れ替える目的】
// ランキングの順位を入れ替える必要があるように、
// 「逆ルートで行きたい!」という希望からスタートとゴールを逆にする処理が必要になることもある。
// 表示順を変えたい時や、条件に応じて中身を交換したい時に使われる。
// 【今までのやり方】
// 一時変数 temp を使って、startとgoalの値を入れ替えていた
// let temp = '';
// temp = start;
// start = goal;
// goal = temp;
// 【分割代入を使った入れ替え】
[goal, start] = [start, goal];
// ↓ どういうこと?イメージ図
// [goal, start] = [ 'Tokyo', 'Osaka' ]
// ↑ ↑ ↑ ↑
// goal ← start start ← goal
// → つまり、お互いの値を同時に入れ替えている!
console.log(start); // 'Osaka'
console.log(goal); // 'Tokyo'
}
- スプレッド構文+レスト構文 ※rest=「残り」
-
レスト構文:受け取って1つにまとめる → "左辺"に使う。
const [first, ...others]
スプレッド構文:広げて展開する → "右辺"に使う。[70, 90, 80, 85, ...moreScores];
→ どちらも...
がポイント
'use strict';
{
const moreScores = [77, 88];
// 【スプレッド構文】配列の中身(要素)を "展開" して、別の配列に入れる
// → moreScoresの[77, 88]をscoresの末尾に展開して入れる
const scores = [70, 90, 80, 85, ...moreScores];
// 【分割代入】配列の最初の1つだけをfirstに、
// 残りすべてをothersという1つの配列にまとめて受け取る
// → 「残り全部まとめて」受け取る構文が【レスト構文】(...others)
const [first, ...others] = scores;
console.log(first); // 70(最初の1つだけ)
console.log(others); // [90, 80, 85, 77, 88](残りすべてをまとめて配列に)
- プリミティブ型(基本データ型) vs 配列(オブジェクト)代入時の挙動の違い:プリミティブ型 は「値そのもの」がコピーされるので、後から変更しても元の値には影響しない
- 一方、配列やオブジェクト は「参照(アドレス)」がコピーされるため、片方を変更するともう片方にも影響する。 しっかり複製したいときは、スプレッド構文などで「中身ごとコピー」する必要がある
'use strict';
{
// プリミティブ型
// let num = 10;
// const numBackup = num; // ← 中身「10」をそのままコピー
// num = 99;
// console.log(num); // 99(上書きしたから)
// console.log(numBackup); // 10(コピー元とは別物!)
// 上記処理を配列で行うと...
// const nums = [10, 20, 30];
// const numsBackup = nums; //← 中身じゃなく、「場所」をコピー
// nums[0] = 99;
// console.log(nums);// [99, 20, 30]
// console.log(numsBackup); // [99, 20, 30]。← あれ、変わっちゃってる!
// コピーしたいときはスプレッド構文!
const nums = [10, 20, 30];
const numsBackup = [...nums]; // ← これで中身をコピーできる!
nums[0] = 99;
console.log(nums); // [99, 20, 30]
console.log(numsBackup); // [10, 20, 30] ← ちゃんと別物!
}
- データ構造編まとめ(感想)
配列の表示方法の様々なパターンや代入のルールなど、コードを書く上で必須となる知識が詰まっていたセクションだった。しっかりと記憶に刻み込みたい。
JavaScript入門 DOM編(全22回)
- DOM(Document Object Model):画面の描画と連動し、コード編集を行ったら、その変更が即座に画面へ反映される仕組み
- 基本的にDOM操作では要素(p要素,section要素など)を取得した後にその要素を操作(テキストやスタイルを変更)するという構造になっている
-
querySelector('セレクタ')
を使うと、特定のHTML要素をJavaScriptから取得できる
例:'p'
,'.class名'
,'#id名'
などのCSSセレクタを指定 -
.addEventListener('click', () => {...})
を使うと、クリックなどのイベントに処理を追加できる
例:ボタンを押したら文字を変える、色を変える、非表示にする…等の動作を定義できる -
.textContent
プロパティを使うと、要素の中のテキストを変更できる
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
// console.log('Clicked');
document.querySelector('p').textContent = 'こんにちは';
// コンソール画面ではなく、pタグでちゃんと画面に文字列を表示させる
// OKボタンを押すと'Hello'が'こんにちは'に変わる処理が行われる
});
// querySelector('')の中に
// 取得したい要素を選択するための
// CSSセレクターを文字列で渡す
// addEventListener()の中に
// ➀'イベントの種類',
// ➁アロー関数でクリックした時に処理したい内容
// () => {処理内容};
// 2種類を入れる
// ここまで書くと、ボタンを押し、
// コンソールに「Clicked」と表示される仕組みが完成する
// console.log('Hello');
}
- ボタンをクリックしたらスタイルが変わる,スタイル操作用:
classList
- 要素のスタイルを変更するには、CSSでクラスを定義してから、
classList
を使う。クラス追加:classList.add
、クラス削除:classList.remove
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My JavaScript</title>
<style>
.pink-bg {
background: pink;
}
.red-border {
border: 2px solid red;
}
.green-color {
color: green;
}
</style>
</head>
<body>
<p class="green-color">Hello</p>
<button>OK</button>
<script src="./main.js"></script>
</body>
</html>
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
document.querySelector('p').classList.add('pink-bg', 'red-border');
document.querySelector('p').classList.remove('green-color');
// p要素を取得し、クラスを追加するためにclassList.addとする。
// ()内:p要素に追加したいクラス名 ※先頭の.(ドット)は要らない!!
// ,(カンマ)区切りで複数渡せる。
// 削除したいクラスはclassList.removeとする。
});
}
- クラスの切り替え(ON/OFF)には
classList.toggle
が便利 - 上記コードのように
.add()
/.remove()
を使うと、「追加」「削除」を明確に制御できる一方、同じクラスをON/OFFしたいだけならtoggle()
を使うと簡潔に書ける!
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
document.querySelector('p').classList.toggle('pink-bg');
// クラスがなければ追加、あれば削除(ON/OFFの切り替え)
});
}
- 補足:
toggle()
を使わずに if文で切り替えることもできる classList.contains('クラス名')
は、そのクラスを持っているかどうか判定するのに便利- ↓このように条件分岐で書けば、切り替え時の処理を柔軟にカスタマイズできる!
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
if (document.querySelector('p').classList.contains('pink-bg') === false) {
document.querySelector('p').classList.add('pink-bg');
} else {
document.querySelector('p').classList.remove('pink-bg');
}
// クラスの有無を確認し、自分で制御したいときはこのように書く
});
}
☆ classListの使い分け早見表
メソッド | 主な用途 | よくある使用シーン例 |
---|---|---|
classList.add() |
クラスを追加 | ✅ ボタンを押したら表示状態にする(例: モーダル表示) |
classList.remove() |
クラスを削除 | ✅ ボタンを押したら非表示にする(例: 閉じるボタン) |
classList.toggle() |
クラスのON/OFFを自動で切り替える | ✅ ボタン1つで表示/非表示を交互に切り替えたいときなど |
classList.contains() |
クラスを持っているかどうか確認する | ✅ 状況によって処理を分けたいとき(ON/OFFで挙動が違う場合) |
☆補足:どれを使えばよいか?
-
add/remove → 「ONにする or OFFにする」どちらか一方だけの操作を明示したいときに使う
(例:「開くときだけ処理したい」「消すだけのボタン」など) -
toggle → 状態を毎回切り替えるだけでOKなときに使う
(例:「開く⇔閉じる」を1ボタンでやりたいとき) -
contains → 今の状態を見て条件分岐させたいときに使う
(例:「開いている時だけこの処理をしたい」など)
- 複数の要素を取得するには、
document.querySelectorAll()
を使う - これで取得されるのは、「配列のように並んだリスト」 なので、1つずつ処理するために
forEach()
を使う必要がある -
.textContent
などをまとめて直接使おうとするとエラーになる(1つずつアクセスする必要がある)
<body>
<ul>
<li>Taro</li>
<li>Jiro</li>
<li>Saburo</li>
</ul>
<button>OK</button>
<script src="./main.js"></script>
</body>
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
document.querySelectorAll('li').forEach((li) => {
// 複数の要素を処理する場合(この場合はリストの3項目)、
// querySelectorAll()とforEach(反復処理)を組み合わせる必要がある
li.textContent = 'Changed!'; // Taro,Jiro,Saburoが同時に「Changed!」に
});
});
}
☆querySelector
vs querySelectorAll
使い分け早見表
※getElementById()
も存在するが、書き方としてもう古い上にforEach
が使えないので、今後は使わないほうがよい!!
メソッド | 主な用途 | 使い方の特徴 |
---|---|---|
querySelector() |
1つ目の要素だけ取得したいとき | CSSセレクタ形式で指定。1個だけ対象。 |
querySelectorAll() |
複数の要素すべてを取得したいとき |
forEach() などで1つずつ処理する。 |
- 特定の要素の取得
<body>
<ul>
<li class="target">Taro</li>
<li id="second">Jiro</li>
<li class="target">Saburo</li>
</ul>
<button>OK</button>
<script src="./main.js"></script>
</body>
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
document.querySelectorAll('.target').forEach((li) => {
// 特定のリストだけ取得したい場合、
// その項目のHTMLにクラス名(今回は.target)を付けて、
// js側をquerySelectorAll('.target')とする。
// ※予備で付けたID('#second')のみ動かすことも可。
li.textContent = 'Changed!';
});
});
}
☆HTMLを編集しなくても、jsのDOM操作だけで要素を追加できる
-
createElement('li')
:新しいli
タグを生成する -
appendChild()
:親要素の末尾(1番最後) に追加する -
insertBefore()
:親要素内の指定した要素の前に追加する -
confirm()
:ユーザーに確認ダイアログを表示
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
// 新しい <li> 要素を作成する
const liElement = document.createElement('li');
// テキストを設定
liElement.textContent = 'Hanako';
// ▼ 要素の追加パターン①:末尾に追加(appendChild)
// 実行結果:Taro → Jiro → Saburo → Hanako(←いちばん最後に追加される)
// document.querySelector('ul').appendChild(liElement);
// ▼ 要素の追加パターン②:指定した要素の「直前」に追加(insertBefore)
// 実行結果:Taro → Hanako → Jiro → Saburo(←Jiroの前に割り込む)
// 第1引数:追加したい要素(liElement)
// 第2引数:目印となる要素(ここでは「Jiro」)
// document.querySelector('ul').insertBefore(
// liElement,
// document.querySelector('#second')
// );
// ▼ 要素の削除(確認ダイアログでOKを押すと「Jiro」が消える)
if (confirm('Sure?') === true) {
document.querySelector('#second').remove();
}
});
}
- フォーム部品の値は
.value
で取得,変更ができる(例:テキストフォームの内容やドロップダウンリストなど)
<body>
<!-- <input type="text"> -->
<textarea></textarea>
<button>OK</button>
<script src="./main.js"></script>
</body>
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
// alert(document.querySelector('input').value);
// ↑ textContentではない!!
// フォーム部品の値にアクセスするにはvalueを使う!!
// 結果:OKボタンを押すと、
// テキストフォームに入力した内容のアラートが出せる。
document.querySelector('textarea').value = '';
// ''の部分=空文字を代入→
// ボタンをクリックしたらtextareaの中の値がクリアされる
});
}
- フォーム部品の値 取得:注意➀!テキストフォームの値やドロップダウンリストは
querySelector
で取得できるが、ラジオボタンの場合はquerySelectorAll
+forEach
を使う必要がある!!(また、HTMLのinput
タグ内はname
属性が要る!!) - 理由:ラジオボタンは、見た目は1つの選択肢に見えても、HTML上は個別の
<input>
タグの集合体。そのため、「複数ある中からどれが選ばれているか」を調べるには、1つずつchecked
状態を判定する必要がある!
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
// すべてのラジオボタンを取得してループ処理
document.querySelectorAll('input').forEach((radio) => {
// checked === true なら選択されているラジオボタン
if (radio.checked === true) {
alert(radio.value); // 選ばれた値をアラートで表示
}
});
});
}
- フォーム部品の値 取得:注意②!チェックボックスの場合も
querySelectorAll
+forEach
を使う必要があるが、さらにここでは配列処理,push
やjoin
も組み合わせる! - 理由:チェックされた項目の数だけアラートが表示されてしまうため!!
- +選ばれた値を一括で表示するには
push()
で配列にためて、join()
で文字列にまとめるのがベストなため
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const colors = []; // 複数の値を保持するために配列を使う
// 空の配列で初期化する
document.querySelectorAll('input').forEach((checkbox) => {
if (checkbox.checked === true) {
colors.push(checkbox.value);
}
});
alert(colors.join(','));
// 反復処理が終わったら、アラートで colors の値を文字列にして表示
// 色の名前の間にカンマ(チェックした色 → red,green と出る。)
});
}
☆実用的な例!input
イベントで、入力した文字を文字数カウント
- これまでの例では「ボタンを押したとき」に
.value
を取得していたが、input
イベントでは入力のたびにリアルタイムで値の変化を監視できる - つまり、「値をいつ取得するか」の違いがあり、
input
は即時反応が必要な場面(例:文字数カウントやバリデーション) に最適
<body>
<input type="text">
<p></p>
<script src="main.js"></script>
</body>
'use strict';
{
// 入力欄に文字が入力されるたびにイベントが発火
// ▼ イベントの使い分け:'input'は text や textarea に使うイベント
// 'change'はラジオやチェックボックス用
document.querySelector('input').addEventListener('input', () => {
const pElement = document.querySelector('p'); // 結果を表示するpタグ
const inputElement = document.querySelector('input'); // 入力されたテキスト
// 入力文字そのものを表示する場合はこちら
// pElement.textContent = inputElement.value;
// 文字数だけを表示する
pElement.textContent = inputElement.value.length;
});
}
}
☆補足:イベントの使い分け(input / change):input
イベントとchange
イベントはどちらもフォーム入力の変化に反応するが、使い分けが必要
-
input
イベント:文字入力中にもリアルタイムで反応(例:テキストやテキストエリア) -
change
イベント:選択が確定されたときに反応(例:ラジオやチェックボックス)
フォーム部品 | イベントタイプ | 説明(いつ反応するか) |
---|---|---|
テキスト入力欄 | input |
入力するたびに即時反応 |
テキストエリア(複数行入力) | input |
入力するたびに即時反応 |
プルダウンリスト |
input /change
|
選択肢を変更した瞬間(input でもOK) |
ラジオボタン | change |
選択肢をクリックして変更した時のみ |
チェックボックス | change |
チェック/解除をした瞬間 |
- (テキストフォームに)フォーカスを当てた時の動作用:
focus
イベント - フォーカスを外した時の動作用:
blur
(ブラー)イベント -
ページを読み込んだと同時にフォーカスを当てておく動作用:
focus()
イベント
※用途によって記述位置が異なるので注意!!
'use strict';
{
document.querySelector('input').addEventListener('focus', () => {
// フォーカスを当てた時の動作
document.querySelector('p').textContent = 'English only!'; // メッセージ表示
});
document.querySelector('input').addEventListener('blur', () => {
// フォーカスを外した時の動作
document.querySelector('p').textContent = ''; // テキストフォームの文字を消す
});
// ページを読み込んだと同時にフォーカスを当てておく動作
document.querySelector('input').focus();
}
☆keydown
イベント:どのキーが押されたか取得する
- 文章全体に対してイベントリスナーを設定したい場合、
document
に対して直接addEventListener
する - 引数名は何でもよいが、一般的にイベントの
e
が使われる -
e.key
は、キーボードで押されたキーの“名前(文字列)”を取得できるプロパティで、 例えば「a」キーを押すと"a"
、「Enter」キーを押すと"Enter"
という文字列が返される。この値をp
要素のtextContent
に代入すれば、ユーザーが押したキーの内容をそのまま画面に表示することができる - この仕組みは、左右キーでスライドを切り替える画像ギャラリーや、Enterキーでフォームを送信する機能、W/A/S/Dキーでキャラクターを動かすゲームなど画面を動かすUIに応用できる
<body>
<p></p>
<script src="main.js"></script>
</body>
'use strict';
{
document.addEventListener('keydown', (e) => {
document.querySelector('p').textContent = e.key;
});
}
☆mousemove
イベント:マウスの動きを追って、X座標/Y座標の位置を表示
e.clientX
/e.clientY
:マウスカーソルが、ブラウザの表示領域(ビューポート)の中でどこにあるかを「X座標(横)」「Y座標(縦)」として数値で返すプロパティ- お絵かきツールや、マウスで動かすゲームを作れる
プロパティ | 何の値? | 単位 | 例 |
---|---|---|---|
e.clientX |
ブラウザ左上からの横方向の位置 | px |
X: 100 → 左から100pxの位置 |
e.clientY |
ブラウザ上端からの縦方向の位置 | px |
Y: 200 → 上から200pxの位置 |
'use strict';
{
document.addEventListener('mousemove', (e) => {
document.querySelector('p').textContent = `X: ${e.clientX} Y: ${e.clientY}`;
// ':'(コロン)があるのでテンプレートリテラルを使う
});
}
☆submit
イベント:HTML
に記入したform
タグ内のフォームに入力した文章をフォームの下に表示できる。ただし、再読み込みによるフォームデータ削除を防ぐため、submit
イベントを使う際は必ずe.preventDefault();
(ブラウザの“標準の動作”をキャンセル)を記述すること
→ ユーザーにとって自然な操作(Enter送信など)を活かしたいなら、form
+submit
+preventDefault
が基本パターン!
処理したいこと | どうする? |
---|---|
入力内容を送信せず画面に表示 |
submit イベント+preventDefault()
|
Enterキーで送信させたい |
<form> タグを使う |
<body>
<form>
<input type="text">
<button>OK</button>
</form>
<p></p>
<script src="main.js"></script>
</body>
'use strict';
{
document.querySelector('form').addEventListener('submit', (e) => {
// ページの再読み込みを防ぐ
e.preventDefault();
// 入力欄の値をpタグに表示
document.querySelector('p').textContent = document.querySelector('input').value;
// 【復習】.value:inputタグの中に入力された値(文字列)を取得するためのプロパティ
});
}
重要トピック➀:「属性操作」
🔰「属性操作」とは?
- HTML要素には、
src
やhref
のような「属性」がある。これらの値を JavaScriptから直接書き換えることで、表示や挙動を動的に変更できる
✏️ 基本ルール
- 属性操作の基本は、
要素.属性名 = 値;
<img src="dog.png">
<a href="https://dotinstall.com">リンク</a>
// src属性の書き換え(画像切り替え)
document.querySelector('img').src = 'cat.png';
// href属性の書き換え(リンク先の変更)
document.querySelector('a').href = 'https://256times.com';
- HTMLで使われている属性名(src、hrefなど)と同じ名前のプロパティを使うのが基本!
⚠️ 注意が必要な「3つの属性」
①class
属性は .class
ではなく .className
を使う
-
class
は JavaScript の予約語のため、プロパティ名としては使えない
// ↓これは構文エラーになる
// element.class = 'red-border';
// 正しくは className を使う
element.className = 'red-border'; // ※既存のクラスを上書きしてしまう
- 既に他のクラス(例:pink-bg)が付いている場合は、空白で区切って全て書く必要あり
element.className = 'pink-bg red-border';
- ✅推奨:classList.add() を使う!
element.classList.add('red-border');
- 既存のクラスにそのまま追加される
-
.remove()
や.toggle()
も使える - 今までの学習で使っていた方法。基本はこちらを使えばOK
②disabled
/checked
/selected
はtrue
/false
で制御する
- これらは「ある/なし」で状態を表す属性
<button disabled>OK</button>
- ↑これを JS で制御するには:
const btn = document.querySelector('button');
btn.disabled = true; // ボタンを無効にする
btn.disabled = false; // ボタンを有効にする
- 同様に:
checkbox.checked = true; // チェックをつける
option.selected = true; // セレクトで選ばれた状態にする
- ✅ これらは 「状態属性」 と呼ばれ、
true
/false
で操作するのが基本ルール。
③checked
の補足:以前は「取得」だけを使っていた
// チェックされているラジオボタンを取得
if (radio.checked === true) {
alert(radio.value);
}
- → ここでは
.checked
は状態の確認(読み取り)として使っていた - →
.checked = true
のように状態の操作(書き込み) として使う方法が登場
→.checked
は「取得と設定の両方ができる」プロパティ!
☆まとめ:属性操作の基本早見表
属性 | 操作例 | 説明 |
---|---|---|
src |
img.src = 'cat.png' |
画像の切り替え |
href |
a.href = 'https://〜' |
リンク先の変更 |
className |
p.className = 'a b' |
クラス名を一括で上書き |
classList |
p.classList.add('c') |
クラスを追加(推奨) |
disabled |
btn.disabled = true / false |
ボタンの有効/無効を切り替え |
checked |
checkbox.checked = true |
チェックを付ける |
selected |
option.selected = true |
セレクトボックスの選択状態にする |
☆補足:この章で新たに出てきたキーワード
キーワード | 出現タイミング | 覚え方/メモ |
---|---|---|
.className |
初登場(class属性操作) | 基本は classList 、上書き時のみ使用 |
.disabled |
初登場 | 状態属性 → true/false で切り替え |
.selected |
初登場 | セレクトボックスで選択状態を設定 |
.checked |
既出(取得)→今回で「設定」も可 | 状態の取得/設定どちらもできる |
重要トピック②:「style属性」
-
element.style
は、HTMLのstyle属性を直接操作できるプロパティ - CSSと異なり、プロパティ名はキャメルケース(小文字始まり+単語区切りは大文字) で書く。※例:
font-size
→fontSize
、background-color
→backgroundColor
- ⚠️ element.style = 'font-size: 24px' のような書き方はエラーにはならないが無効
→ styleは「オブジェクト」なので、個別のプロパティに代入する形でしか使えない -
style.fontSize = '24px'
のように、文字列として値(単位付き)を代入すればOK。※動的にスタイルを変更したい場面(文字サイズの調整・背景色の切り替えなど)で使う
☆style変更の代表例(対応表)
CSSでの記述 | JSでの書き方 |
---|---|
color: red; |
element.style.color = 'red' |
font-size: 24px; |
element.style.fontSize = '24px' |
background-color: #ccc; |
element.style.backgroundColor = '#ccc' |
border-radius: 8px; |
element.style.borderRadius = '8px' |
<body>
<p style="color: red;">Hello</p>
<button>OK</button>
<script src="main.js"></script>
</body>
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
// document.querySelector('p').style = 'font-size: 24px';
document.querySelector('p').style.fontSize = '24px';
});
}
- DOM編まとめ(感想)
ここまでで最も実用的で、パターンごとに様々な書き方があるなあ、後から見返して使えたら嬉しいな、とのんびりまとめていたら、最後で新知識が怒涛の勢いで登場して混乱。細かいところは継続して詰めるとして、これでなんとか、JavaScript基礎習得セットになっただろうか。学ぶ意欲を絶やさず、このままどんどん深く知識の沼に潜っていきたい。