Javascriptクローズドと変数
5183 ワード
1.クローズドと変数
JavaScriptにおけるスコープのメカニズムは、関数内の任意の変数を含む最後の値しか得られないという副作用を引き出す.クローズドされているのは変数オブジェクト全体で、特別な値ではありません.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
もちろん匿名関数を使って強制的にクローズドの挙動を予想通りにすることができます.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.2 thisオブジェクトについて
閉じたパケットの中でthisオブジェクトを使用すると、いくつかの問題が発生します.thisオブジェクトは実行時に関数に基づいて環境バインディングを実行します.大域関数では、thisはwindowに等しいです.関数がオブジェクトとして扱われる場合、thisはそのオブジェクトに等しいです.しかし、匿名関数の実行環境は大域的であるため、そのthisオブジェクトは通常windowを指す(もちろん、call()とapply()によって環境を変更するとき、thisは他のオブジェクトを指す).
1
2
3
4
5
6
7
8
9
10
11
以上のコードは、大域変数nameを作成しました.属性を含むオブジェクトを作成しました.このオブジェクトは、匿名関数に戻ります.また、getNameFun()の関数を返します.したがって、object.get NameFun()()を呼び出すと、その関数が呼び出され、結果として文字列が返されます.しかし、この例で返される文字列は、グローバルname変数の値である「The Window」である.
しかし、なぜ匿名関数は、そのスコープ(または外部スコープ)を含むthisオブジェクトを取得していないのですか?
各関数は呼び出し時に、そのアクティブなオブジェクトは2つの特殊な変数を自動的に取得します.内部関数は、この2つの変数を検索すると、そのアクティブなオブジェクトだけが検索されますので、外部関数の2つの変数には絶対にアクセスできません.ただし、外部作用領域のthisオブジェクトをクローズドパケットでアクセスできる変数に保存すると、そのオブジェクトにクローズドをかけてアクセスすることができます.
1
2
3
4
5
6
7
8
9
10
11
12
JavaScriptにおけるスコープのメカニズムは、関数内の任意の変数を含む最後の値しか得られないという副作用を引き出す.クローズドされているのは変数オブジェクト全体で、特別な値ではありません.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function
createFunctions(){
var
result=
new
Array();
for
(
var
i=0;i<10;i++){
result[i]=
function
・(){
return
i;
};
}
return
result;
}
var
funcs = createFunctions();
for
(
var
i=0; i < funcs.length; i++){
document.write(funcs[i]() +
"<br />"
・);
}
createFunction関数は、行列を返します.表面的には、それぞれの関数が自分のインデックス値を返すべきだと思われますが、実際には、関数ごとの戻り値は10です.各関数の作用領域チェーンには、createFunctions関数の活動対象が含まれていますので、それらは同じ変数iを参照しています.createFunctions関数が戻ると変数iの値は10になりますが、各関数は変数iを保存する同じ変数オブジェクトを参照していますので、各関数は10に戻ります.もちろん匿名関数を使って強制的にクローズドの挙動を予想通りにすることができます.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function
createFunctions(){
var
result=
new
Array();
for
(
var
i=0;i<10;i++){
result[i]=
function
・(num){
return
function
(){
return
num;
};
}(i);
}
return
result;
}
var
funcs = createFunctions();
for
(
var
i=0; i < funcs.length; i++){
document.write(funcs[i]() +
"<br />"
・);
}
前のcreateFunctions関数を書き換えたら、それぞれのインデックス値が戻ります.ここでは、私たちは直接にクローズドを数値に割り当てず、匿名関数を定義し、その関数の結果をすぐにアレイに与えます.ここの匿名関数にはパラメータnumがあります.つまり、最後の関数が返す値です.各匿名関数を呼び出したとき、変数iに着信しました.関数パラメータは値で渡されるので、変数iの現在値をパラメータnumにコピーします.この匿名関数の内部には、作成され、numにアクセスするためのクローズドが返されています.このように依存して、result配列の各関数にはnum変数のコピーがありますので、それぞれの数値を返します.1.2 thisオブジェクトについて
閉じたパケットの中でthisオブジェクトを使用すると、いくつかの問題が発生します.thisオブジェクトは実行時に関数に基づいて環境バインディングを実行します.大域関数では、thisはwindowに等しいです.関数がオブジェクトとして扱われる場合、thisはそのオブジェクトに等しいです.しかし、匿名関数の実行環境は大域的であるため、そのthisオブジェクトは通常windowを指す(もちろん、call()とapply()によって環境を変更するとき、thisは他のオブジェクトを指す).
1
2
3
4
5
6
7
8
9
10
11
var
name=
"The Window"
;
var
object={
name:
"My object"
・,
getNameFunc:
function
・(){
return
function
(){
return
this
.name;
};
}
};
alert(object.getNameFunc()());
//"The Window"( )
以上のコードは、大域変数nameを作成しました.属性を含むオブジェクトを作成しました.このオブジェクトは、匿名関数に戻ります.また、getNameFun()の関数を返します.したがって、object.get NameFun()()を呼び出すと、その関数が呼び出され、結果として文字列が返されます.しかし、この例で返される文字列は、グローバルname変数の値である「The Window」である.
しかし、なぜ匿名関数は、そのスコープ(または外部スコープ)を含むthisオブジェクトを取得していないのですか?
各関数は呼び出し時に、そのアクティブなオブジェクトは2つの特殊な変数を自動的に取得します.内部関数は、この2つの変数を検索すると、そのアクティブなオブジェクトだけが検索されますので、外部関数の2つの変数には絶対にアクセスできません.ただし、外部作用領域のthisオブジェクトをクローズドパケットでアクセスできる変数に保存すると、そのオブジェクトにクローズドをかけてアクセスすることができます.
1
2
3
4
5
6
7
8
9
10
11
12
var
name=
"The Window"
;
var
object={
name:
"My object"
・,
getNameFunc:
function
・(){
var
that=
this
;
return
function
(){
return
that.name;
};
}
};
alert(object.getNameFunc()());
//"My object"
上記のコードでは、匿名関数を定義する前に、that変数にthisオブジェクトの値を割り当てましたが、閉ループを定義した後に、この変数にもアクセスできます.外部関数でわざわざ宣言した変数です.関数が戻った後も、thisはobjectを参照していますので、object.get Name()を呼び出して、My objectに戻ります.