jsprimerで学んだJavaScriptの基礎まとめ

JavaScriptの基礎を学ぶためにjsprimerという無料の教材を読んで写経しました。

感想

内容は2部構成になっていて、1部でJavaScriptの基礎文法を学び、2部でサンプルのアプリを作成します。

無料ですが文法をしっかり学んだ上でアプリを作ることもできるので、Progateなどをやった後やReact、Vueなどのフレームワークをやる前のJavaScriptの言語仕様を学ぶに最適だと思います。

1部はRubyを学んでいたので、共通するような文法は流し読みでいけたのですが、クロージャーやthis、非同期処理などの理解が特に難しかったです。

いろんな関数が出てくるので、関数の理解が特に重要だなと感じました。

2部では非同期処理を使ってGithubAPIからユーザー情報を取得できるアプリ、Node.jsを使ってMarkdownをHTMLに変換するCLIアプリ、Todoアプリを作りました。

それぞれのコードの説明もされていて、動くコードを書いてからリファクタリングしていくやり方なので基本的にはわかりやすかったのですが、それでもTodoアプリのクラスや関数のつながりや処理の流れを追うのは大変でした。

静的解析ツール、テストなどの周辺のツールについての解説はないので、そこらへんは自分で調べる必要があります。

さっさとJavaScriptの基礎は理解して、Reactの勉強に入ろうと思います。

新しく学んだこと

新しく学んだ重要そうな部分をまとめておきます。

第一部

JavaScriptとは

  • ブラウザだけでなくNode.jsというサーバー側のアプリを作る仕組みでも利用される
  • JavaScriptECMAScriptというどの実行環境でも共通で動作する仕様と、実行環境によって異なる固有の機能で成り立つ
  • JavaScriptは大部分がオブジェクト
  • 開発者が安全にコードを書けるように、strict modeという古く安全でない構文や機能の一部が禁止される実行モードが存在する
  • デフォルトの実行コンテキストであるScriptと、ES2015で導入されたJavaScriptをモジュールとして実行するための実行コンテキストであるModuleがある
  • Scriptはデフォルトでstrict modeではなく、Moduleはデフォルトでstrict mode

コメント

  • //は1行のコメント
  • /* */は複数行のコメント

変数と宣言

  • 変数を宣言するキーワードにはvarletconstがある
  • varは古いキーワードで意図しない動作を作りやすい
  • letconstvarの問題を改善するためにES2015で追加された
  • letは再代入ができ、初期値を指定しない変数も定義できる
  • 初期値を指定しない場合はundefinedという値が未定義であることを表す値になる
  • constは再代入ができない
  • varの問題点
    • 同じ名前の変数を再定義できてしまう
    • 変数の巻き上げ
  • constは初期化した後でも値を変更できるオブジェクトにも使えるので定数ではない

値の評価と表示

  • JavaScriptの多くの実行環境では、ConsoleAPIを使ってコンソールに表示する
  • console.logデバッグとして使える
  • エラーには構文エラーと実行時エラー(ランタイムエラー)の2種類ある
  • 実行時エラーは実行するまでエラーになるかわからないので、エラーの原因を探るデバッグを行う必要がある

データ型とリテラル

  • JavaScriptのデータ型にはプリミティブ型(基本型)とオブジェクトの2つに分類される
  • プリミティブ型は一度作成したらその値自体を変更できないイミュータブルという特性を持つ
  • オブジェクト型は一度作成した後もその値自体を変更できるミュータブルという特性を持つ
  • プリミティブ型は7つある
    • 真偽値
    • 数値
    • 巨大な整数
    • 文字列
    • undefined
    • null
    • シンボル
  • プリミティブ型ではないものオブジェクト型になる
  • データ型の値を直接記述できるように構文として定義されたものがリテラル
  • undefinedはリテラルではなくただのグローバル変数undefinedという値を持っているだけ
  • オブジェクトリテラル{}で新しいオブジェクト作成できる
  • プリミティブ型のデータでもオブジェクトのように参照できる仕組みがあるため、ラッパーオブジェクトを明示的に使う必要はない

演算子

  • 任意の数値を0で除算した結果は、無限大を表す数値であるInfinityとなる
  • NaNNot-a-Numberの略称で、数値ではないがNumber型の値になる
  • ===は同じ型で同じ値である場合にtrueを返す、オブジェクトの場合は参照が同じである場合にtrueを返す
  • ==は同じ型で同じ値である場合にtrueを返すが、異なる型の値であった場合、同じ型になるように暗黙的な型変換をしてから比較するので、意図しない挙動が発生する可能性がある
  • 例外的にnullundefinedの比較のために==が使われることがある
  • 配列やオブジェクトの値を複数の変数に同時に代入できるのが分割代入
  • 暗黙的にfalseに変換される値
    • false
    • undefined
    • null
    • 0
    • 0n
    • NaN
    • ""
  • AND演算子で左辺がfalseの場合、右辺は評価されない、このことを短絡評価という
  • OR演算子は左辺がtrueの場合、右辺は評価されない
  • 評価結果がnullまたはundefinedとなる値をnullishという
  • カンマで区切った式は左から順に評価される

暗黙的な型変換

  • 暗黙的な型変換はバグの原因となるので、型変換をしたい場合は明示的にする
  • Booleanコンストラクタで真偽値に変換できる
  • Stringコンストラクタで数値から文字列に変換できる
  • シンボルは暗黙的な型変換ができない
  • Numberコンストラクタで文字列から数値に変換できる
  • NaNは何と演算してもNaNになり、デバッグが難しくなるので避けるべき

関数と宣言

  • returnの値を省略、またはreturnそのものを省略した場合はundefinedが返される
  • 仮引数と呼び出し時の引数の数が違っても関数を呼び出せる
  • 呼び出し時の引数が少ない場合、余った仮引数にはundefinedが代入される
  • ES2015からはデフォルトで引数を代入できるデフォルト引数を指定できる
  • 呼び出し時の引数が多い場合は、溢れた引数は無視される
  • 引数が固定ではなく、任意の個数の引数を受け取るものを可変長引数という
  • 可変長引数を実現するには、Rest parametersargumentsを使う
  • ES2015から追加されたRest parametersは関数に渡された値が配列として代入される可変長引数
  • argumentsは関数の中でのみ参照できる特殊な変数で、渡された引数の値が全て入っている配列のようなオブジェクト
  • Rest parametesを使えるならargumentsは使わない
  • 関数はオブジェクトの一種で、()をつけると処理を呼び出せて、()をつけないとオブジェクトとして参照できる
  • 関数をあたいとして変数へ代入したものを関数式という
  • 関数宣言は文で、関数式は値として扱う
  • 関数式で名前を持たない関数を代入したものを無名関数という
  • ES2015では無名関数を=>を使ってArrow Funtionで書ける
  • thisの挙動やargumentsを使えないなどの解釈や実装による違いが生まれにくい特徴から、基本的にはArrow Functionを使い、そうでない場合はFunctionを使う
  • 関数の引数として渡された関数をコールバック関数という
  • コールバック関数はいちいち定義するのは面倒なので、無名関数として使うことが多い
  • コールバック関数を引数として使う関数を高階関数という
  • コールバック関数は非同期処理でよく使われる

文と式

  • JavaScriptは文と式から構成される
  • 式は値を生成し、変数に代入できるもの
  • 文は処理する1ステップのことで、変数に代入できない
  • {}で囲んだ部分をブロックという
  • if文などと組み合わせずに単独のブロック文を書くことはほとんどない

条件分岐

  • 1行のif文はブロックを省略できるがわかりづらいので常にブロックで囲むことが推奨される
  • switch文の式は===で評価される
  • switch文はif文の代用より、関数と組み合わせて条件に対する値を返すパターンとして使われることが多い

ループと反復処理

  • while文は他により安全な反復処理の書き方があるので、使う場面は限られる
  • do-while文は条件がfalseでも最初に処理が実行される
  • 配列のforEachメソッドは条件式がなく、配列の全ての要素を反復処理する
  • for...in文はオブジェクトのプロパティに対して反復処理を行う
  • for...in文は親オブジェクトのプロパティまで列挙可能なものを探すので、意図しない結果になる場合がある
  • ES2015で追加されたfor...of文は反復処理時の動作が定義されたオブジェクトの総称であるiterableオブジェクトを反復処理できる
  • Array、String、Map、Setなどはiterableオブジェクト
  • for文などの構文はcontinue文やbreak文を使える
  • 配列のメソッドでは一時的な変数が必要なかったり、処理をコールバック関数として書く

オブジェクト

  • JavaScriptではObjectというどの実行環境でも使えるビルトインオブジェクトが定義されている
  • {}Objectインスタンスオブジェクトになる
  • new演算子でもインスタンスを作成できるが、簡潔な{}を使うべき
  • プロパティの参照では基本的に.を使い、変数を指定したい場合は[]を使う
  • オブジェクトはミュータブルの特性を持つ
  • オブジェクトの初期化時以外にプロパティを追加するとどんなプロパティを持つか分かりにくくなるので、オブジェクト作成時に定義する
  • 存在しないプロパティにアクセスすると、例外ではなくundefinedが返される
  • プロパティの存在を確認するにはin演算子か、Object.hasOwn静的メソッドを使う
  • オブジェクトのプロパティにアクセスするとプロパティ名は暗黙的に文字列に変換される
  • Object.assingメソッドを使うと、オブジェクトのマージや複製ができる

プロトタイプオブジェクト

  • オブジェクトに組み込まれたメソッドをビルトインメソッドという
  • ほとんどすべてのオブジェクトはObject.prototypeプロパティに定義されたprototoypeオブジェクトを継承している
  • prototypeはすべてのオブジェクトの作成時に自動的に追加される、すべてのオブジェクトから利用できるメソッドなどを提供する特殊なオブジェクト
  • prototypeオブジェクトに組み込まれているメソッドをプロトタイプメソッドという
  • インスタンスからプロトタイプメソッドを呼び出せることをプロトタイプチェーンという
  • 同じ名前のプロトタイプメソッドとインスタンスメソッドはインスタンスメソッドが優先して呼び出される
  • ArrayArray.prototypeをもつ
  • Object.create(null)でプロトタイプオブジェクトを継承しない完全に空のオブジェクトを作れる

配列

  • JavaScriptにおける配列は可変長
  • 存在しないインデックスに対してアクセスするとundefinedを返す
  • 配列には未定義の値を持つ要素を含むことができる
  • 配列から要素を検索する目的
    • インデックスを取得する
    • 要素自体を取得する
    • 要素が存在するかの真偽値を取得する
  • 配列の要素の追加、削除
    • 末尾に追加 - push
    • 末尾を削除 - pop
    • 先頭に追加 - unshift
    • 先頭を削除 - shift
    • 任意のインデックスの要素を削除 - Array.prototype.slice
  • ES2015で追加されたSpread構文を使うことで、配列の中に既存の配列を展開できる
  • 破壊的なメソッドは配列オブジェクトそのものを変更し、非破壊的なメソッドは配列オブジェクトのコピーを作成してから変更する
  • 反復処理の中でよく使われるメソッド
    • forEach - 反復処理
    • map - 反復処理を行なって新しい配列を返す
    • filter - 反復処理を行いtrueを返した要素だけの新しい配列を返す
    • reduce - 反復処理を行い、累積値を返す(可読性がよくない)
  • 配列のメソッドはメソッドチェーンといって繋げて実行でき、複数の処理をまとめることができる

文字列

  • JavaScript文字コードUnicodeを採用し、文字をエンコードする方式としてUTF-16を採用している
  • UTF-16はそれぞれの文字を16ビットのビット列に変換するエンコード方式
  • 1文字を表すのに使う最小限のビットの組み合わせをCode Unitという
  • つまり、JavaScriptにおける文字列は16ビットのCode Unitが順番に並んだものとして内部的に管理されている
  • 文字列の厳密比較は以下の条件を満たしていれば同じ文字列となる
    • Code Unitが同じ順番で並んでいるか
    • 文字列の長さが同じか
  • 正規表現リテラルソースコードをパースした段階で評価され、RegExpコンストラクタは通常の関数と同じように呼び出した時に評価される
  • 正規表現リテラルの方が簡潔でパフォーマンスがいいが、変数を使いたい時などはRegExpコンストラクタを使う
  • URLなどの構造的な文字列を扱う場合は専用の関数を使うべき

文字列とUnicode

  • UTF-16を採用するのはJavaScriptの内部であり、ファイルの文字コードは他の文字コードでも問題ない
  • Unicodeにおける文字に対する一意のIDをCode Pointという
  • Code UnitやCode Pointを意識しなくても文字列の処理はできるが、絵文字を使うときはCode Pointを意識する必要がある

ラッパーオブジェクト

  • 真偽値、数値、BigInt、文字列、シンボルにはそれぞれ対応するオブジェクトがあり、それらをラッパーオブジェクトという
  • プリミティブ型の値に対してプロパティアクセスする時、自動で対応するラッパーオブジェクトに変換される
  • ラッパーオブジェクトではなくリテラルを使うべき
  • JavaScriptは全てがオブジェクトであるわけではなく、すべてがオブジェクトのように見えるというのが正しい

関数とスコープ

  • 関数は変数や関数の引数などを参照できる範囲であるスコープを持つ
  • スコープの中で定義された変数はスコープの外からは参照できない
  • 関数の仮引数はスコープに紐づけられる
  • 関数によるスコープを関数スコープという
  • {}で囲まれた範囲をブロックスコープという
  • for文はループごとに新しいブロックスコープを作成した
  • スコープはネストでき、内側のスコープから外側のスコープにある変数は参照できる
  • 内側から外側のスコープへ順番に変数を探すことをスコープチェーンという
  • もっとも外側のスコープをグローバルスコープといい、グローバルスコープにある変数をグローバル変数という
  • むやみにグローバル変数を定義しない
  • 変数を参照できる範囲をできるだけ小さくする
  • letは変数を宣言する前に参照するとエラーになるが、varundefinedになるのでエラーにならない → 変数の巻き上げ
  • varブロックスコープを無視する
  • functionキーワードを使った関数宣言も宣言より前に呼び出せる巻き上げが起こる
  • letconstが追加されるまでは、関数スコープを作ってグローバルスコープの汚染を避けるために即時実行関数を使われていた
  • どの識別子がどの変数を参照しているかを静的に決定する性質を静的スコープといい、JavaScriptの変数や関数の参照先は静的スコープで決まる
  • JavaScriptには参照されなくなった不要なデータをメモリから解放するガベージコレクションという仕組みがある
  • 静的スコープとメモリ管理の仕組みによって、関数内から特定の変数を参照し続けることで関数が状態を持てる仕組みのことをクロージャーという
  • 関数はオブジェクトであるためプロパティに状態を持たせることもできるが、関数の外からプロパティを変更できるため推奨されない
  • クロージャーはグローバルスコープの汚染を防いだり、関数に状態を持たせるために使う

関数とthis

  • thisは読み取り専用のグローバル変数のようなもので、条件によって参照先が異なる
  • thisが実際に使われるのはメソッドで、メソッド以外では使うべきではない
  • 実行コンテキストにおけるthis
    • 最も外側のスコープでは実行コンテキストによってthisの参照先は変わるので、使うべきではない
    • スクリプトにおけるthisの参照先 → グローバルオブジェクト(実行環境ごとに異なる)
    • モジュールにおけるthisの参照先 → undefined
  • 関数とメソッドにおけるthis
    • Arrow Function以外の関数におけるthis
      • 関数宣言、関数式におけるthisの参照先 → undefined
      • メソッド呼び出しにおけるthisの参照先 → ベースオブジェクト
    • strict modeではないとthisundefinedの場合、グローバルオブジェクトを参照するように変換されてしまう
    • Arrow Functionにおけるthis
      • Arrow Functionはthisをもてない
      • 参照先 → 外側のスコープのthis
  • thisは定義したときではなく実行時に決定されるので、関数にthisが含まれていると意図しない結果が発生する場合がある
    • 対策
      • メソッドは関数ではなくメソッドとして呼ぶ
      • callapplybindメソッドを使って明示的にthisを指定する
  • 明示的にthisを指定することで、本来undefinedとなる部分にオブジェクトを渡すことができる
  • callapplyの違いは引数への値の渡し方が異なる
  • bindthisが束縛された関数を作る
  • コールバック関数はただの関数として呼ばれベースオブジェクトがないので、thisundefinedになる
    • 対策
      • thisthatのような一時変数に代入する
      • Arrow Functionでコールバック関数を使う(ES2015からはこっちの方が簡潔)

クラス

  • JavaScriptではES2015まではクラスがなく関数を使ってクラスのようなものを表現していた → 書き方を統一するためにES2015でclass構文が導入される
  • class構文はプロトタイプベースの継承の仕組みを使って関数でクラスを表現している
  • クラスは必ずコンストラクタを持つ
  • クラスは関数式のように値として定義できる
  • コンストラクタ内でのthisインスタンスのオブジェクトを参照する
  • new演算子インスタンスが返されることが期待されるため、コンストラクタでreturn文を使って任意のオブジェクトを返すべきではない
  • 関数で表現したクラスは関数として呼び出せるが、class構文で定義したクラスは関数として呼び出すことはできない
  • インスタンス間で共有されるメソッドをプロトタイプメソッドという
  • 外から読み書きして欲しくないプロパティには_をつける慣習がある
  • 外からアクセスできるプロパティをPublicクラスフィールド、外からアクセスできないプロパティをPrivateクラスフィールド
  • 静的メソッドにはstaticをつける
  • 静的メソッド内のthisはクラス自身を参照する
  • プロトタイプメソッドはプロトタイプオブジェクトに、インスタンスオブジェクトのメソッドはインスタンスオブジェクトに定義されるので、同時に定義しても上書きされない
  • インスタンスオブジェクトのメソッドがプロトタイプメソッドより優先して呼び出される
  • classも関数オブジェクトの1種であるため、自動的にprototypeプロパティにプロトタイプオブジェクトが作成される
  • class構文のメソッド定義はプロトタイプオブジェクトのプロパティとして定義される
  • インスタンスにメソッドを定義していなくても、インスタンスの生成時にクラスのプロトタイプオブジェクトへの参照が保存されるので、プロトタイプチェーンによってインスタンスからクラスのプロトタイプメソッドを呼び出せる
  • インスタンスはどのクラスから作られたかと、そのプロトタイプオブジェクトを知っている
  • オブジェクトがプロパティを探す時は、まずインスタンス自身から探し、次に[[Prototype]]の参照先を探し、どこにも無かったらundefinedを返す
  • super()で子クラスから親クラスのconstructorを呼び出せる
  • コンストラクタは親クラスから実行される
  • ビルトインオブジェクトも継承できる

例外処理

  • tryの中で例外が発生するとcatchの処理が実行される
  • finallyの処理は必ずtryの最後に実行される
  • throwで例外を投げることができる
  • デバッグに役立つスタックトレースを得るために、例外はErrorオブジェクトのインスタンスを投げるべき
  • ビルトインエラーの種類
    • ReferenceError - 存在しない変数や関数が参照された時のエラー
    • SyntaxError - 構文エラー
    • TypeError - 値が期待される型ではない場合のエラー
  • エラーに関するログ出力はconsole.errorを使う

非同期処理:Promise/Async Function

  • コードをを順番に1つずつ実行する処理を同期処理という
  • 同期処理では現在の処理が終わるまで次の処理に進めない
  • JavaScriptの処理はブラウザのメインスレッドで実行される
  • メインスレッドはUIに関する処理も行われるため、他の処理が実行されると表示が更新されなくなる
  • 同期処理とは反対に処理の終了を待たずに次の処理を実行するものを非同期処理という
  • 非同期処理も大部分はメインスレッドで実行される
  • 非同期処理は処理を一定の単位ごとに分けて切り替えながら実行する並行処理として扱われる
  • 実行環境によってメインスレッドとは別のスレッドで実行できるものもある
  • 非同期処理では例外をキャッチできない
  • 非同意処理の外からは非同期処理の中で例外が発生したかわからないため、例外が発生したことを非同期処理の中から外に伝える方法が必要
Promise
  • PromiseはES2015で導入された非同期処理の状態や結果を表現するビルトインオブジェクト
  • 非同期処理が成功すればresolve()を呼び、失敗すればreject()を呼び出す
  • 成功時のコールバック関数はthenメソッドで登録し、失敗時のエラー処理はthenではなくcatchメソッドを使う
  • Promiseではコンストラクタの処理で例外が発生した場合には自動的に例外がキャッチされ、thencatchで登録したエラー時のコールバック関数が呼び出される
  • Promiseのインスタンスには3つの状態がある
    • Fulfilled - 成功
    • Rejected - 失敗または例外発生
    • Pending - インスタンスを作成した時の初期状態
  • 複数の非同期処理を順番に扱いたい場合はPromiseをメソッドチェーンでつなぐPromiseチェーンを使う
  • 成功時、失敗時のどちらの場合でも呼び出したい処理はfinallyメソッドに書く
Async Function
  • Async FunctionはES2017で追加された非同期処理を行う関数を定義する構文で、Promiseの上に作られている
  • Async Functionは関数の前にasyncをつけ、必ずPromiseインスタンスを返す
  • awaitを使うことで、Promiseチェーンの可読性を解決し、非同期処理を同期処理のように扱える
  • awaitは右辺のPromiseインスタンスがFulfilledまたはRejectedになるまで非同期処理の完了を待ち、Promiseの状態が変わると次の行の処理を再開する
  • awaitはPromiseがRejectedになった場合に例外をキャッチする
  • awaitはAsync Functionの直下でのみ使える

Map/Set

  • MapとSetはES2015で追加されたデータの集まりであるコレクションを扱うビルトインオブジェクト
Map
  • Mapはキーと値の組み合わせであるマップを扱うためのビルトインオブジェクト
  • newで新しいMapオブジェクトを作成する
  • コンストラクタにキーと値の配列を初期値として渡すことができる
  • ObjectをMapとして使うメリット
    • リテラル表現があるため作成しやすい
    • JSONに変換しやすい
    • APIやライブラリなどの関数がマップとしてObjectが渡される設計になっている
  • Mapを使うメリット
    • プロトタイプのメソッドやプロパティとキーが衝突しない
    • キーにはあらゆるオブジェクトを使える
    • マップのサイズを簡単に知ることができる
    • 要素を簡単に列挙できる
Set
  • Setは重複する値がないことを保証したコレクション
  • 要素は順序とインデックスを持たない
  • newで新しいSetオブジェクトを作成する
  • 重複する値は無視される

JSON

  • JSONはオブジェクトリテラル、配列リテラル、各種プリミティブ型の値を組み合わせたもの
  • JSONではオブジェクトのキーを必ずダブルクォートで囲まなければならない
  • JSON.parseメソッドで、JSONの文字列をオブジェクトに変換できる
  • 実際のアプリでJSONを扱うのは外部のプログラムとデータを交換する用途がほとんど
  • 外部のプログラムが送ってくるデータが常にJSONとは限らないため、常に例外処理をすべき
  • JSON.stringifyメソッドで、オブジェクトをJSONの文字列に変換できる

Date

  • Dateオブジェクトは常にnew演算子を使ってインスタンスを作成する
  • Dateでは機能が不十分なので、ライブラリを使うことが一般的

Math

  • Mathオブジェクトは数学的な定数と関数を提供するビルトインオブジェクト
  • コンストラクタではないため、インスタンスを作らずに静的なプロパティやメソッドとして提供する

ECMAScriptモジュール

  • モジュールとは変数や関数などをまとめたJavaScriptの1ファイル
  • モジュールは依存性の高いコードをまとめて、再利用するために使う
  • モジュールを外部から使えるようにすることをエクスポート、モジュールを読み込むことをインポートという
  • エクスポート・インポートそれぞれに名前付きとデフォルトの2種類ある
  • 名前付きにはエイリアスを使って違う名前でエクスポート/インポートできる
  • デフォルトエクスポートはモジュールごとに1つしかエクスポートできない特殊なエクスポート
  • 関数は宣言と同時にエクスポートできるが、変数はできない
  • デフォルトインポートはデフォルトエクスポートに名前をつけてインポートする
  • import * asで全ての名前付きエクスポートをまとめてインポートでき、モジュールごとの名前空間となるオブジェクトを宣言し、そのプロパティを使ってアクセスする
    • ファイルをモジュールとして読み込むにはscriptタグのtype属性をmoduleとする(指定しない場合構文エラーとなる)

第二部 応用編

  • Node.jsはJavaScript実行環境のひとつで、V8JavaScriptエンジンで動作する
  • Node.jsにはnpmというパッケージマネージャーが同梱されている
  • npmコマンドではなく、npxコマンドを使うとnpmで公開されている実行可能なパッケージのインストールと実行をまとめてできる

Ajax

  • HTMLのコンテンツと構造をJavaScriptから操作できるオブジェクトをDOMといい、動的なWebアプリを作るためには不可欠
  • DOMはブラウザが実装しているAPIで、HTMLをブラウザで読み込む時に生成され、HTMLのタグと入れ子構造を木構造で表現する
  • Fetch APIを使うことで、ページを再読み込みすることなくHTTP通信を行い指定したURLからデータを取得できる
    • fetchメソッドでリクエストを送信でき、Promiseを返す
    • 返されたPromiseインスタンスはレスポンスを表すResponseオブジェクトでresolveされる
    • response.statusでHTTPのステータスコードを取得できる
    • Fetch APIが標準化される前はXMLHttpRequestが使われていた
  • JavaScriptでHTML要素をDOMに追加する方法は2つある
    • HTML文字列をinnerHTMLプロパティにセットする
    • Elementオブジェクトを生成して手続き的にツリー構造を構築する
  • HTMLのエスケープはライブラリで行うのが一般的
  • バッククォートの前に関数を書くとタグ関数として呼び出せる

Node.jsでCLIアプリ

  • Node.js環境ではconsole.logの出力先は標準出力になる
  • JavaScriptのコードをNode.jsで実行するにはnodeコマンドを使う
  • Node.jsではエントリーポイントとなるJavaScriptファイルを作成し、そのファイルをnodeコマンドの引数に渡して実行するのが基本
  • Node.jsのグローバルオブジェクトはglobalオブジェクト
  • Node.jsの実行プロセスの情報の取得と操作ができるprocessargvというグローバル変数のプロパティによってコマンドラインの引数にアクセスできる
  • アプリでコマンドライン引数を扱うときは一度パースして扱いやすい値に整形するのが一般的
  • ECMAScriptモジュールの前はCommonJSモジュールが使われていて、相互運用性に注意する
  • Node.jsでファイルの読み書きを行うにはfsモジュールを使う

Todoアプリ

  • JavaScriptから扱うid属性は慣習的にjs-からはじめる名前にする
  • イベントの発生を元に処理を進めることをイベント駆動(イベントドリブン)という
  • 直接DOMを更新する問題
    • 状態をすべてHTMLに埋め込み、文字列として扱わなければならない
    • 更新箇所が増えると操作に対する処理が複雑になる
  • 直接DOMを更新する問題を解決するにはモデルを使って状態を管理する
  • 表示は操作ではなくモデルが変化したタイミングで更新する
  • 状態が変化したらイベントを発生させる
  • イベントはディスパッチとリスナーによって成り立つ

開発を補助するツール

  • Babelは古いブラウザにも対応させるために、新しい構文を古い構文に変換するツール
  • TypeScriptはJavaScriptに静的型づけの構文を追加した言語
  • モジュールバンドラーはJavaScriptのモジュール依存関係を解決し、複数のモジュールを1つのJavaScriptファイルに結合するツールで、webpackがよく使われる