Open7
JavaScript基礎を徹底していくスレ
「知ったつもりでいる」「分かった気になっている」から「説明できる」状態を目指してアウトプットしていく。内容は雑多な学習メモ。
var, let, constの違い
- 基本的にconstを使う
- 書き換えが可能だと意図しないところで書き換わってバグの原因になる可能性がある
- 再代入したい場合のみletを使う(e.g. for文)
- 現在ではvarを使うことはまずない
var | let | const | |
---|---|---|---|
再宣言 | 〇 | × | × |
再代入 | 〇 | 〇 | × |
スコープ | 関数 | ブロック | ブロック |
ホイスティング | undefined | エラー | エラー |
ホイスティング(巻き上げ)とは
- 変数を宣言した際に宣言文が関数の先頭に持ち上げられること
- 変数の初期化は記述した場所で行われるが、変数の宣言は関数の先頭に移動する
- そのため、varで宣言した変数はどこでも使用可能になる。初期化より前では変数の値はundefinedになる
- バグの原因になる可能性があるので、let以降は修正された
- letやconstでもホイスティング自体は行われているがエラーになる、ということらしい
console.log(foo) // undefined
var foo = 1
console.log(foo) // 1
console.log(bar) // Uncaught ReferenceError: can't access lexical declaration 'foo' before initialization
let bar = 1 // constにしても同様
console.log(bar) // 1
DOMとは
- Document Object Model の略
-
公式ドキュメントには以下のように定義されている
- The Document Object Model (DOM) is a programming API for HTML and XML documents. It defines the logical structure of documents and the way a document is accessed and manipulated.
- 「DOMはHTML・XMLのためのプログラミングAPIである。ドキュメントの論理構造とそのアクセス・操作の方法を定義している」
- APIって言葉に既にProgrammingて含まれていると思うけどProgramming APIとは?
- 「JavaScriptなどのプログラミング言語でHTML要素を操作できるようにするインタフェース」て感じ?
- 元のHTMLを直接変更することはできないけど、DOMを操作することで動的にWebページを変更することができる
- The Document Object Model (DOM) is a programming API for HTML and XML documents. It defines the logical structure of documents and the way a document is accessed and manipulated.
- HTMLドキュメントを直接解読して表示するのではなく、DOMをもとに画面表示する
- DOMのレンダリングはHTMLソースの上から下へ順番に処理していくので、HTMLを表示するときは、まずheadタグ内を処理してからその後bodyタグ内を処理して画面に表示する。
- 記述する場所によってJavaScriptで記述した内容を処理するタイミングが変わる
- headタグ内
- JavaScriptの処理をしてからbodyタグ内を処理する
- 外部ファイル
- ファイルの読み込み(ダウンロード)をしてからbodyタグ内を処理する
- bodyタグ内の最下部
- bodyタグ内のJavaScriptの記述前の処理をしたあとにJavaScriptの処理をする
- headタグ内
-
JavaScriptはbodyタグ内の最下部に記述するのがおすすめ
- headタグ内に記述するとbodyタグ内の処理を行う前にJavaScriptの記述を処理する(外部ファイルの場合はファイルの読み込みをする)ため、表示に時間がかかってしまうから
- 記述する場所によってJavaScriptで記述した内容を処理するタイミングが変わる
- 参考: 業務ができる中級者になるためのJavaScript入門(DOM編)
?, ??, || 演算子の違い
結論
- || と ?? はよく似ているが、|| は左辺がnullかundefinedである場合に右の値を返すのに対し、??は左辺がnullやundefinedだけでなくfalsyな値(false, 0, NaN, ""など)であった場合に右の値を返す
- ? は条件に応じて値を返すために使用される
||と??の使い分け
- || は0もfalseと評価してしまうため、0も返す値として指定して良い場合は代わりに??を使う
// 「user.MPが未定義の場合はデフォルトの値として100を返す」ことを意図したコード
const MP = user.MP || 100 // しかし、この書き方だと0のときにfalseとなって100が返ってしまう
const MP = user.MP ?? 100; // この書き方なら0の場合も正しく代入できる
条件演算子 (?:)
- JavaScriptで唯一の三項演算子
- 先頭のオペランドの値がtruthyな値なら2番目のオペランドを、falsyな値なら3番目のオペランドを返す
- そこは??じゃなくて||に近いんだ
for/in とfor/of
forEach()とmap()の違い
結論
新しい配列を生成したい場合はmap()を使う
-
forEach()
- 繰り返し処理を行うメソッド
- 配列のすべての要素に対して処理を行う
- 返り値はなし (returnするとundefinedが返る)
-
map()
- 繰り返し処理を行い、新しい配列を作るメソッド
- forEachメソッドと同様、配列のすべての要素に対して処理を行う
- 実行結果が配列データとして返る
どちらも共通して、元の配列は変更されない(= 非破壊的なメソッド)
(一方でpush, unshift, pop, sortなどは元の配列を変更してしまう破壊的なメソッド)
// forEach の例
let numbers = [1, 2, 3, 4, 5];
const doubledNumbers = [];
const forEachResult = numbers.forEach(num => {
doubledNumbers.push(num * 2);
});
console.log("forEach Result:", forEachResult); // 出力: undefined
console.log("forEach Array:", doubledNumbers); // 出力: [2, 4, 6, 8, 10]
console.log("Original Array after forEach:", numbers); // 出力: [1, 2, 3, 4, 5](元の配列は変更されない)
// map の例
numbers2 = [1, 2, 3, 4, 5];
const mapResult = numbers2.map(num => num * 2);
console.log("map Result:", mapResult); // 出力: [2, 4, 6, 8, 10]
console.log("Original Array after map:", numbers2); // 出力: [1, 2, 3, 4, 5](元の配列は変更されない)
bind(), call(), apply()の違い
- bind()は新しい関数を返す
- call()とapply()は関数を即時実行するが、applly()は引数に配列を渡せる
特徴 | call | apply | bind |
---|---|---|---|
使用方法 | func.call(thisArg, arg1, arg2, ...) |
func.apply(thisArg, [argsArray]) |
const boundFunc = func.bind(thisArg, arg1, arg2, ...) |
引数の渡し方 | 個別の引数を直接渡す | 引数を配列で渡す | 固定の引数を渡し、新しい関数を生成 |
関数の即時呼び出し | する | する | しない |
返り値 | 関数の戻り値 | 関数の戻り値 | 新しい関数 |