javascriptあれこれ備忘録
javascriptに関する覚え書き。
関数は"first class"オブジェクトである。ファーストクラスだと、
- 無名リテラルで表現OK
- 変数に格納OK
- データ構造に格納OK
- 関数に引数として渡せる
- 関数の戻り値にできる
- 実行時に定義できる
- 関数名と変数名は無関係
などなど。。。
//無名リテラルで表現OK function(){ //<--- 名前の無い関数リテラルを宣言 return "boo"; } //変数に格納OK var hoge = function(){ //<--- 変数hogeを宣言し、無名関数で初期化している return "boo"; }; //関数名と変数名は無関係 function foo() {} alert(foo); // 関数名 "foo" を含む文字列をアラートする var bar = foo; alert(bar); // アラートする文字列には変わらず関数名 "foo" が含まれている //実行時に定義できる->つまりクロージャーを作成できる function hoge(){ var daba = "Hello"; return bobo(); function bobo(){ return "Hey" + daba; } }
変数の宣言方法
変数はvar キーワードで宣言する。
グローバルスコープにおいて宣言された変数は、グローバルオブジェクトのプロパティとして作成される。
ブラウザの場合、windowオブジェクトのプロパティとなる。
宣言されていない変数にアクセスしようとするとReferenceError 例外が発生する。
初期化されていない変数にはundefinedがセットされる。
関数を定義する3つの方法とそれぞれの違い
//function文で定義(これは関数宣言) //この場合、関数を定義しているスコープに関数名と同じ名前の変数が作成され、この関数が代入される function name([param[, param[, ... param]]]) { statements } //function演算子で定義(これは関数式) //この場合Functionオブジェクトを返す。nameを指定すれば名前付きのFunctionオブジェクトを返す。 function [name]([param[, param[, ... param]]]) { statements } //Functionコンストラクターで定義 new Function([param[, param[, ... param]]], functionBody) //"function"キーワードは、文脈によって、関数宣言にも、関数式にもなる。 //式の一部となっている場合、if文内など、ネストの中にある場合などのばあい、、 //functionキーワードは関数式として構文解析される。 ただし、ブラウザによっては(IE8など)名前付き関数式を関数宣言解釈するものがあるので、注意。
関数には名前を付けることができるが、その名前は自身の関数内からのみ参照可能である。
function something_001(){} alert(something_001); //<--- function something_001(){}と表示される var bobo = function something_002(){}; alert(something_002); //<--- エラーになる(グローバルスコープからsomething_002にはアクセスできない) //上のsomething_001の例は、 var something_001 = function something_001(){} //と同じ。だからエラーにならない。
ホイスティング
あるスコープ内の変数宣言・関数宣言は、その位置に関わらずスコープの先頭に持ち上げられる(ホイスティングという)。
潜在エラーを回避するため、変数宣言はできる限りスコープの先頭で行うのがよい。
var myvar = "my value"; (function() { console.log(myvar); // undefined var myvar = "local value"; })(); hogehoge(); function hogehoge(){ alert("HOGE----");// HOGE----がアラートされる } //さらに、関数宣言は初期化されていない変数宣言をオーバーライドする var hogehoge; alert(hogehoge); //<--- function(){〜}がアラートされる var hogehoge = "hogehoge"; alert(hogehoge); //<--- "hogehoge"がアラートされる
スコープ
javascriptでは、ソースコード内の位置によって変数のスコープが作成される(レキシカルスコープという)。
関数内で宣言された変数のスコープは、関数内のみ。同様に引数のスコープもその関数内のみ。
単なるコードブロックはスコープを作らない。オブジェクトによってスコープが作られる。従って、if文なども同様にスコープを作らない。
var x = 1; { x = 2; } console.log(x) //2
//スコープチェーン
あるスコープ内に変数定義が見つからない場合、上位のスコープにさかのぼって変数定義をサーチする。
this 演算子
関数をコールする際に、”."演算子で結びつけられているオブジェクトの参照が、thisに渡される。結びつけられていない場合はグローバルオブジェクトの参照がthisに渡される。
グローバルスコープでのthisは、グローバルオブジェクトの参照を返す。
関数内のthisは、それを利用しているオブジェクトへの参照を返す。
new演算子
new foo(...)の場合、次のステップで演算が行われる: