kidoOooOoooOOom

IT系で開発やってます

開眼JavaScript

JavaScriptの勉強始めたのでメモ。

開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質

開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質

  1. JavaScriptオブジェクト
    • JavaScriptの世界では、ほぼすべてがオブジェクトそのものか、もしくはオブジェクトのようにふるまう。
    • オブジェクトとは、名前と値を持つプロパティを格納するコンテナにすぎない。
    • new 演算子を伴って呼び出された場合、コンストラクタ関数は特別な役割をする。
      • コンストラクタ関数のthisの値として、これから新たに生成されるオブジェクトを設定する。
      • 本来return文を宣言しない場合にはfalse相当の値を返すところ、コンストラクタ関数はその代わりに新たに生成されるオブジェクト(thisで参照されるオブジェクト)を返す。
    • コンストラクタ関数は大文字で始めるのが通例
    • オブジェクトの生成はリテラルを用いたほうが便利。リテラルはnew演算子が行うことを隠ぺいしているにすぎない。
    • null, undefiend, 'string', 10, true, false などはオブジェクトではなくプリミティブ型
      • プリミティブ型は値がメモリに保存され操作さえる。比較も値そのものを比較する。
      • プリミティブ型はオブジェクトのように扱うとオブジェクトのようにふるまう。
    • すべてのコンストラクタインスタンスコンストラクタ関数にポイントする constructorプロパティを持つ
  2. オブジェクトとプロパティを扱う
    • ドット記法とブラケット記法でオブジェクトのプロパティにアクセス
      • 一般的にはドット記法を用いるが、数値始まりや予約語を用いたプロパティにはブラケット記法でないとアクセスできない。
    • オブジェクト内に存在しないプロパティにアクセスしようとすると、JavaScriptは常にプロトタイプチェーンをたどってそのプロパティを探し当てようとする。
    • hasOwnProperty()を使って、プロパティがプロトタイプチェーン経由ではないことを確認できる。
    • in演算子を使って、オブジェクトがプロパティを保持しているかどうかを確認できるが、プロトタイプチェーンも全て辿ってしまう。
    • WebブラウザなどのJavaScript実行環境は「ホストオブジェクト」と呼ばれる複数のオブジェクトを持っている。
      • Webブラウザ環境では、windowオブジェクトと、windowオブジェクトに保持されているすべてのオブジェクトがホストオブジェクト。
      • JavaScript言語仕様とホストオブジェクトの間には何も関係が無い
      • ブラウザは一般的にホストオブジェクトとネイティブオブジェクトを区別する
    • Underscore.jsを使ってオブジェクトを拡張できる。便利なユーティリティライブラリ。
  3. オブジェクト(Object())
    • オブジェクトリテラルとは{}や{a:10,b:20}のように、波括弧を使用してプロパティを格納した状態の表現。
    • Object()コンストラクタ関数の prototypeプロパティがプロパティチェーンの終着点
  4. 関数(Function())
    • 一般的には function演算子(関数リテラル)を使う方法で生成する。
    • インスタンスメソッドの apply(thisArg, argArray) は、thisArgにthisの値を渡し、argArrayに渡された配列を引数リストとして関数を実行する。
    • インスタンスメソッドの call(thisArg [, arg1 [, arg2 [, ...]])は、thisArgにthisの値を渡し、関数を実行する。第2引数以降の引数が実行関数の第1引数〜となる。
    • 関数は常に値を返す。return文を記述していない場合などは undefinedが返される。
    • JavaScriptの関数は第1級関数。第1級関数は wikipediaなどで参考。第一級関数 - Wikipedia
    • 関数の実行方法
    • 関数式は関数定義の後に()演算子を付与することによってその場で実行する。
    • 関数宣言を使って定義される前に関数を実行することが可能。これを関数巻き上げと呼ぶ。
  5. グローバルオブジェクト
    • JavaScriptのコードはオブジェクトに格納されている必要があります。
      • Webブラウザ環境でJavaScriptコードを書く場合には、windowオブジェクト内にJavaScriptを格納し、windowオブジェクト内で実行する必要がある。このwindowオブジェクトに相当するものが「グローバルオブジェクト」。
    • JavaScriptはあらかじめ定義されている関数をいくつか持っている。これをグローバル関数とよぶ。
    • グローバルオブジェクト直下に格納されているのが、グローバルプロパティ、グローバル変数
    • グローバルスコープ下で var演算子を伴って変数を宣言する場合、その変数はグローバル変数となり、var演算子を使用しない場合はグローバルプロパティとして宣言される。違いとしては delete演算子で消せるかどうか。
    • グローバルオブジェクトは暗黙的に参照されるため、通常は参照を使うことはない。
      • 明示的にグローバルオブジェクトを指定する場合、計算コストがほんのわずか上昇する。
  6. this
    • 関数が実行される際、thisキーワードの値が設定される。このときに設定される値は、関数を呼び出すオブジェクトへのリンク。
    • 全ての関数に渡される thisの値は、関数が実行時に呼びだされる際のコンテクストに依存する。ここは覚えておかないといけない JavaScriptの「癖」
    • 入れ子関数内では、thisはグローバルオブジェクトを参照する。残念な仕様。
      • これを避けるためには、一般的に入れ子関数からアクセスできるスコープに var that = this などを保持して、その thatを使用することで thisを見失うことがない。
      • call() や apply() では引数に thisArg があるため、これを用いることで thisをコントロールできる。
    • new 演算子を使ってコンストラタ関数を呼び出す場合、thisの値はコンストラクタ関数内で新たに生成されるインスタンスを参照する。
    • プロトタイプメソッド内のthisは生成されるインスタンスを参照する
  7. スコープとクロージャ
    • JSでは、コードが実行されるコンテクストにスコープが割り当てられる。スコープには、グローバルスコープ、ローカルスコープ(関数スコープともいう)、evalスコープの3つのタイプがある。
      • 関数内で var を使って宣言された変数にはローカルスコープが適用され、その変数は宣言した関数内の他の式からのみ参照することができる。
    • JSは他の言語でよくみるブロックスコープは持たないので注意!
    • スコープチェーンの検索は最初に発見した値を返す。
    • スコープは関数実行時ではなく関数定義時に決められる。
    • クロージャはスコープチェーンによって生成される
      • クロージャを一言で表すと「スコープチェーンによって存在する変数への参照を保持している関数」と言える。クロージャが生成されるとスコープチェーン上の変数への参照は保持される。親関数スコープで定義されている変数は、たとえ親関数自身が使われなくなったとしても、それらを参照するクロージャが生き残っている限り保持される。
  8. 関数のprototypeプロパティ
    • 関数の prototypeプロパティは、Function()のインスタンスを生成する際にJavaScriptが自動的に付与するオブジェクト。コンストラクタ関数に定義されている prototypeプロパティは、new演算子を使って、もしくはリテラルを使って生成されたインスタンスオブジェクトからコンストラクタ関数を参照できるリンクを提供する。このときコンストラクタ関数自身がコンストラクタを持っている場合にはさらにさかのぼるリンクが発生し、通常は Object.prototypeにさかのぼるまで連鎖する。このリンクの連鎖をプロトタイプチェーンと呼ぶ。
    • プロトタイプチェーンによって、生成された各インスタンスの間でコンストラクタ関数が(prototypeプロパティに)持つメソッドやプロパティを「共有」「継承」することが可能になる。
    • プロトタイプチェーンは最初に見つけたプロパティを返す。
  9. 配列(Array())
  10. String()
  11. Number()
  12. Boolean()
  13. プリミティブ型文字列、数値、真偽値
  14. null
    • nullを使って、オブジェクトのプロパティが値を持っていないkとおを明示的に示すことができる。
    • プロパティは設定されているものの、何らかの理由で値を使用することができない場合は、プロパティが空の値を持っていることを明示するために undefined ではなく nullを使うべき
  15. undefined
    • 2つの異なる方法で使用される。
      • 宣言された変数に値が割り当てられていないとき
      • アクセスしようとしているオブジェクトプロパティが定義されておらず、かつプロトタイプチェーンでも発見できないとき