スコープの分類
グローバル・スコープ
グローバルオブジェクトのプロパティとメソッド
一番外側で宣言された変数とメソッド
非厳密モード宣言されていない定義済み変数
関数のスコープ
関数スコープで生成される変数とメソッド
ブロックレベルのスコープ
関数の自己実行によってシミュレートされるブロックレベルのスコープ 原則はやはり関数のスコープです。
スコープの連鎖
は、現在の実行環境と上位の実行環境からの一連の変数オブジェクトで構成され、現在の実行環境がアクセス権を満たす変数や関数への秩序あるアクセスを保証します。
変数にアクセスするとき、インタプリタはまず現在のスコープで識別子を探し、見つからなければ親スコープに移動します。
スコープチェーンの先頭はグローバルオブジェクトです。
実行コンテキストスタックとスコープチェーン
実行コンテキスト・スタックはコード実行時に決定され、スコープは実行コンテキストが作成されたときに決定されます。
スコープ・チェイニングとプロトタイプ継承ルックアップの違い
通常のオブジェクトのプロパティを探していて、それが現在のオブジェクトやそのプロトタイプに見つからない場合、undefinedが返されますが、探しているプロパティがスコープチェーンに存在しない場合はReferenceErrorがスローされます。
クロージャ
クロージャの作成時
クロージャは特別な種類のオブジェクトです。
実行コンテキストと、その実行コンテキストで作成された関数です。
Bの実行時に、Aの変数オブジェクトの値がアクセスされると、クロージャが作成されます。
多くの書籍や記事では、ここで生成されたクロージャは関数Bの名前で参照されますが、Chromeでは、クロージャは実行コンテキストAの関数名で参照されます。
クロージャの例1
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
3
3
3
閉鎖による変化
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = (function (i) {
return function(){console.log(i);}
})();
}
data[0]();
data[1]();
data[2]();
クロージャの例2
// iをvarで定義する
var data = [];
for (let i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
3
3
3
var data = [];
// letを使ってiを定義する
for (let i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
1
2
3
forループをブロック・スコープにするにはletsを使います。
タンタンマウント
var data = [];
for (var i = 0; i < 3; i++) {
(function(i){
data[i] = function () {
console.log(i);
};
})(i)
}