フロントエンド学習記(仮題)

主にフロントエンドについて学習した事を記録・メモしていきます。

【学習ログ】MDN JavaScript チュートリアル (19 回目)

はじめに

この記事は、JavaScript チュートリアルの学習ログです。

学習したもの

MDN にある JavaScriptチュートリアルを学習しました。


MDN JavaScript コーナー

チュートリアル
  ┣ 完全な初心者向け
  ┃
  ┣ 中級者向け
  ┃ ┣ クライアントサイド Web API
  ┃ ┣ JavaScript 「再」入門
  ┃ ┣ JavaScript のデータ構造
  ┃ ┣ 等価比較と同一性(本日の学習箇所)
  ┃ ┗ クロージャ(本日の学習箇所)
  ┃
  ┗ 上級者向け
    ┣ 継承とプロトタイプチェーン
    ┣ Strict モード
    ┣ JavaScript 型付き配列
    ┣ メモリ管理
    ┗ 同時実行モデルとイベントループ


概要

チュートリアルで習った事の概要は下記の通りです。

等価比較と同一性

JavaScript の等価比較や同一性についての詳細を学習する。

クロージャ

クロージャの詳細について学習する。

ノート・メモ

(1) 等価比較と同一性

  • ES2015 には、 4 種類の等価性アルゴリズムがあります。

    • 抽象的な等価性比較 (Abstract Equality Comparison) (==)

    • 厳格な等価性比較 (Strict Equality Comparison) (===)

      Array.prototype.indexOf, Array.prototype.lastIndexOf, case の一致で使用。

    • ゼロの同値 (SameValueZero)

      %TypedArray% と ArrayBuffer コンストラクター、 Map と Set の操作、 ES2016 で追加された String.prototype.includes で使用されます。

    • 同値(SameValue)

      上記以外のすべての状況で使用されます

  • どの演算子を使用するかは、どのような比較を行いたいかに依存します。簡単に言えば、

    • 二重等号 (==) は二つのものを比較する前に型変換を実行し、 NaN, -0, +0 を IEEE 754 に準拠して特別扱いします (よって NaN != NaN, -0 == +0 になります)。

    • 三重等号 (===) は二重等号と同じ比較を (NaN, -0, +0 の特別扱いを含めて) しますが、型変換を行いません。 もし型が異なれば、 false が返されます。

    • Object.is は型変換を行わず、 NaN, -0, +0 の特別扱いもしません (これらの特殊な数値を除いて === と同じ動作をします)。

  • これらの区別はプリミティブ値の扱いについてのことです。いずれの場合も引数が概念的に似た構造を持つかどうかを比較する訳ではありません。 プリミティブ値ではない x および y オブジェクトが同一の構造を持っていてもオブジェクトが異なれば、上記のいずれの形でも false と評価されます。

  • === による厳格な等価性

    • 厳格な等価性は、2 つの値が等しいか比較します。比較対象の値はどちらも、比較する前に別の値へ暗黙のうちに変換されることはありません。

    • 値が異なる型の場合、それらの値は等しくないとみなします。

    • 値が同じ型で数値ではない場合、同じ値であれば等しいとみなします。

    • 最後に、どちらの値も数値である場合、どちらも NaN ではなく同じ値である、あるいは一方が +0 かつもう一方が -0 であるときに等しいとみなします。

    • 厳密な等価性は、たいていの使い方で正しい比較になります。数値以外のあらゆる値において、これは「値が自分自身と等しい」という明快な解釈を用います。

    • 数値においては、2つの極めて特殊なケースを扱えるようにわずかに異なる解釈を用います。

      • 1つ目は浮動小数点数の 0 には正と負の符号付きが存在することです。これは、ある種の数学的な解を表すために役立ちますが、ほとんどの場合は +0 と -0 の違いを意識せず、厳格な等価性ではこれらを同じ値として扱います。

      • 2つ目は浮動小数点数には非数 NaN の概念があることです、これは例えば正の無限大に負の無限大を加算するといった一定の数学的に明確ではない問題達の解を表します。厳格な等価性では NaN を他のどの値 (自分自身も含む) とも等しくないものとして扱います。((x !== x) が true になる唯一の場合は x が NaN である場合です。)

  • == による緩い等価性

    • 緩い等価性は、両方の値を共通の型に変換した後で、2 つの値が等しいか比較します。(片方あるいは両方の変換が行われた) 変換処理後に、最終的な等価性の比較は === と全く同じ振る舞いです。

    • 緩い等価性は対称的であり、任意の値 A および B において、 A == B と B == A の意味は常に同じ意味です (変換処理を適用する順序を除く)。

    • 伝統的にも、また ECMAScript によれば、すべてのオブジェクトは undefined や null に対して大雑把には等価でないとしています。しかし、ほとんどのブラウザは、ごく一部のオブジェクト (特に、あらゆるページの document.all オブジェクト) が、いくつかの状況においては値 undefined のように振る舞う ことを認めています。

    • 緩い等価性もそのようなものの一つです、A が undefined に相当するオブジェクトである場合に限り、 null == A および undefined == A は true になります。それ以外のどのオブジェクトも undefined および null と大雑把には等価とはなりません。

  • Same-value 等価性

    • すべての状況で 2 つの値が機能的に同一かを判断します。Same-value 等価性は Object.is メソッドによって提供されます。
  • Same-value-zero 等価性

    • Same-value 等価性に似ていますが、 +0 と -0 は等しいとみなします。

(2) クロージャ

  • クロージャは、関数と、その関数が宣言されたレキシカル環境の組み合わせです。

  • レキシカルスコープ

    • レキシカルスコープ、つまりパーザーが関数がネストされている時に変数名を解決する方法。

    • 変数のスコープはソースコード内の位置によって決定され、入れ子にされた関数は外側のスコープで宣言された変数にアクセスすることができます。

  • クロージャ

    • クロージャは関数とその関数が作られた環境という 2 つのものの組み合わせです。この環境は、クロージャが作られた時点でスコープ内部にあったあらゆる変数によって構成されています。

    • クロージャを使うと、データ (環境) をそれを操作する関数と結びつける事が出来ます。これはオブジェクトを使ってデータ (オブジェクトのプロパティ) を 1 つかそれ以上のメソッドと結びつける事が出来るオブジェクト指向プログラミングと明らかに類似しています。

    • したがって、メソッドを 1 つだけ持つオブジェクトを使いたくなるような状況ならば、どんな時でもクロージャを使う事ができます。

    • ウェブではこのような状況はよくあります。私たちが書く JavaScript のコードは大半がイベントベースです。つまり、ある動作を定義し、それを click や keypress といったユーザーによって引き起こされるイベントに取り付けます。私たちのコードの多くはコールバック、すなわちイベントに反応して実行される単独の関数として取り付けられます。

  • クロージャでプライベートメソッドを模倣する

    • Java などの言語ではプライベートなメソッドを宣言することが出来ます。これは同じクラス内にあるほかのメソッドからのみ呼び出せるメソッドのことです。

    • JavaScript にはこういった機能は組み込まれていませんが、クロージャを使うとプライベートメソッドを模倣する事ができます。プライベートメソッドはコードへのアクセスを制限するのに役立つだけではなく、コードのパブリックインターフェースが不要なメソッドでいっぱいになるのを防ぐため、グローバル名前空間を管理するのに非常に有効です。

  • パフォーマンスへの配慮

    • あるタスクを実行する時、クロージャが必要とされていないのにいたずらに関数を他の関数の中に作成するのは、スクリプトのパフォーマンスに悪影響を及ぼすのであまり賢いやり方ではありません。

    • 例えば、新しくオブジェクト/クラスを作成する時、一般的にメソッドはオブジェクトのコンストラクタの中で定義するのではなく、オブジェクトのプロトタイプに結びつけるべきです。コンストラクタの中で定義してしまうと、コンストラクタが呼び出されるたびに (つまりオブジェクトが作成されるたびに) メソッドが再代入されてしまうことになるからです。

分かった事

(1) 等価比較と同一性

(2) クロージャ

  • レキシカルスコープやクロージャの概要が理解できたと思います。

分からなかった事

(1) 等価比較と同一性

  • 「Same-value 等価性」、「等価性の比較を理解するためのモデル?」、「Object.is と三重等号の使いどころ」、「注意: Object.is と NaN」については、さっぱり分からなかったです。

(2) クロージャ

  • クロージャを使用すべきケースと使用すべきでないケースの具体例が理解しきれていないと感じます。

まとめ

今回は、「等価比較と同一性」・「クロージャ」の2つのチュートリアルを学習しました。どちらも難しく感じると共に理解できる範囲もあったので、自身の成長も感じれた回になりました。

上級者編も頑張って学習していきたいと思います。

最後までご覧頂きありがとうございました。