JSの匿名関数のコンテキスト環境について話します.
6341 ワード
熱心なネット友達の関心と質問を受けて、私はまたJSの匿名関数のコンテキスト環境について詳しく分析して実験しました.次に私のこの問題に対する考えを皆さんと共有します.
キーワード
JavaScriptの対象システムにおいて、キーワードthisを使用する場所:オブジェクトの方法(または属性)が呼び出された場合、この方法(または属性)を呼び出すオブジェクトの例を指す.例を挙げます
thisを使う理由
オブジェクトを実装するとき、開発者がどのような変数名を使うかは常に確認できません.thisを使って、同じ関数をどこでも再利用できます.次の例を考えてください.
オブジェクトやthisキーワードで変数を参照しないと、ECMAScriptはローカル変数やグローバル変数と見なされます.この関数は、カラーというローカルまたはグローバル変数を検索しますが、見つけられません.結果はどうですか?この関数は警告に「null」を表示します.
関数と方法
JavaScriptでは関数と方法を明確に区別していないからです.そのためコードによってはおかしく見えるものがあります.
テスト2では、Obj 1/obj 2対foo()の呼び出しが普通です. テスト3のcall()とappy()は特殊です.このテストでは、foo()は依然として一般的な関数として呼び出されていますが、JavaScriptの言語特性は、call()/apply()の時に、オブジェクトのインスタンスに入ってfoo()のコンテキスト環境に現れるthisキーの参照を指定することができます.なお、この時のfoo()は、オブジェクトメソッドではなく通常の関数で呼び出されています.このテストはfoo関数のthisを元の参照「window」から後のパラメータオブジェクトに変更しただけです.テスト3の結果に惑わされないようにしてください.以下の例を見てください.
テスト3の結果には明らかに文字列「call a method,by object:」が含まれていません.この呼び出しは明らかにmethodではなく、functionであると説明しています.
しかし、詳しく考えてみると、厳密には大域foo()関数も方法であり、そのコンテキスト環境(window)の方法であるため、以下の3つの呼び出し方法は等価である.
署名関数と匿名関数のコンテキスト環境
以上の基礎があります.署名関数と匿名関数のコンテキスト環境を比べてみます.彼らの間に何か違いがありますか?例は以下の通りです.
上の2つの関数の例の比較から、匿名関数のコンテキスト環境もwindowであり、windowオブジェクトとも言える方法であり、匿名にすぎず、window.foo()のように直接に呼び出して実行することはできない(もしこのように実行を呼び出すことができれば、呼び出しフォーマットはwindow.匿名関数である().もちろん冗談です.そうでなければ、JSが匿名関数を規定する規則は必要ないです. このような条件では、署名関数と匿名関数は、コンテキスト環境ではなく、実行の仕方を呼び出しているように見える. 二つの関数のコンテキスト環境が同じで、関数がオブジェクトである以上、二つの異なる関数のオブジェクトを作って、その中の属性(または方法)にアクセスしてみてください.
上の詳細例を通して、きっと分かります.以上に間違いがあれば、ご叱正をお願いします.
キーワード
JavaScriptの対象システムにおいて、キーワードthisを使用する場所:オブジェクトの方法(または属性)が呼び出された場合、この方法(または属性)を呼び出すオブジェクトの例を指す.例を挙げます
function foo(){
this.property = "red";
this.method = function(){...}
}
thisを使う理由
オブジェクトを実装するとき、開発者がどのような変数名を使うかは常に確認できません.thisを使って、同じ関数をどこでも再利用できます.次の例を考えてください.
function showColor() {
alert(this.color);
};
var oCar1 = new Object;
oCar1.color = "red";
oCar1.showColor = showColor;
var oCar2 = new Object;
oCar2.color = "blue";
oCar2.showColor = showColor;
oCar1.showColor(); // "red"
oCar2.showColor(); // "blue"
なお、オブジェクトの属性を参照する場合は、thisキーが必要です.例えば、以下のコードを採用すると、showColor()方法は実行できません.function showColor() {
alert(color);
};
オブジェクトやthisキーワードで変数を参照しないと、ECMAScriptはローカル変数やグローバル変数と見なされます.この関数は、カラーというローカルまたはグローバル変数を検索しますが、見つけられません.結果はどうですか?この関数は警告に「null」を表示します.
関数と方法
JavaScriptでは関数と方法を明確に区別していないからです.そのためコードによってはおかしく見えるものがあります.
function foo() {
// this
if (this===window) {
document.write("call a function.", "<br />");
}
else {
document.write("call a method, by object: ", this.name, "<br />");
}
}
function MyObject(name) {
// this new
this.name = name;
this.foo = foo;
}
var obj1 = new MyObject("obj1");
var obj2 = new MyObject("obj2");
// 1:
foo(); //Output=>call a function.
// 2:
obj1.foo(); //Output=>call a method, by object: obj1
obj2.foo(); //Output=>call a method, by object: obj2
// 3: “ ”
foo.call(obj1); //Output=>call a method, by object: obj1
foo.apply(obj2); //Output=>call a method, by object: obj2
テスト2では、Obj 1/obj 2対foo()の呼び出しが普通です. テスト3のcall()とappy()は特殊です.このテストでは、foo()は依然として一般的な関数として呼び出されていますが、JavaScriptの言語特性は、call()/apply()の時に、オブジェクトのインスタンスに入ってfoo()のコンテキスト環境に現れるthisキーの参照を指定することができます.なお、この時のfoo()は、オブジェクトメソッドではなく通常の関数で呼び出されています.このテストはfoo関数のthisを元の参照「window」から後のパラメータオブジェクトに変更しただけです.テスト3の結果に惑わされないようにしてください.以下の例を見てください.
function foo() {
// this
if (this===window) {
document.write("call a function.", "<br />");
}
else{
document.write("call a function or method.", "<br />");
}
}
function MyObject(name) {
// this new
this.name = name;
this.foo = function(){
document.write("call a method, by object: ", this.name, " ; and then ");
foo();
};
}
var obj1 = new MyObject("obj1");
var obj2 = new MyObject("obj2");
// 1:
foo(); //Output=>call a function.
// 2:
obj1.foo(); //Output=>call a method, by object: obj1 ; and then call a function.
obj2.foo(); //Output=>call a method, by object: obj2 ; and then call a function.
// 3: “ ”
foo.call(obj1); //Output=>call a function or method.
foo.apply(obj2); //Output=>call a function or method.
テスト3の結果には明らかに文字列「call a method,by object:」が含まれていません.この呼び出しは明らかにmethodではなく、functionであると説明しています.
しかし、詳しく考えてみると、厳密には大域foo()関数も方法であり、そのコンテキスト環境(window)の方法であるため、以下の3つの呼び出し方法は等価である.
foo();
this.foo();
window.foo();
これは私にJSの中のもう一つの機構を思い付かせます.関数は対象で、対象は属性と方法があります.方法はまた関数であることができます.このようにして、「鶏の卵、卵の卵」のようなサイクルにします.署名関数と匿名関数のコンテキスト環境
以上の基礎があります.署名関数と匿名関数のコンテキスト環境を比べてみます.彼らの間に何か違いがありますか?例は以下の通りです.
//
function foo() {
// this
if (this===window) {
document.write("foo ( this ) window.", "<br />");
}
}
//
window.foo(); //Output=>foo ( this ) window. foo window , foo window
this.foo(); //Output=>foo ( this ) window. this window
foo(); //Output=>foo ( this ) window. foo ,this
// , window。
//
(function(){
// this
if (this===window) {
document.write(" ( this ) window.", "<br />");
}
})() //Output=> ( this ) window.
上の2つの関数の例の比較から、匿名関数のコンテキスト環境もwindowであり、windowオブジェクトとも言える方法であり、匿名にすぎず、window.foo()のように直接に呼び出して実行することはできない(もしこのように実行を呼び出すことができれば、呼び出しフォーマットはwindow.匿名関数である().もちろん冗談です.そうでなければ、JSが匿名関数を規定する規則は必要ないです. このような条件では、署名関数と匿名関数は、コンテキスト環境ではなく、実行の仕方を呼び出しているように見える. 二つの関数のコンテキスト環境が同じで、関数がオブジェクトである以上、二つの異なる関数のオブジェクトを作って、その中の属性(または方法)にアクセスしてみてください.
//
function foo() {
this.color = "red";
}
var f = new foo();
alert(window.f.color); // Output=>red
alert(this.f.color); // Output=>red
alert(f.color); // Output=>red
alert(window.color); // Output=>undefined
alert(this.color); // Output=>undefined
alert(color); // Output=>js error:color
// , f window, window , f window。
//
(function(){
this.color="blue";
})();
alert(window.color); // Output=>blue
(function(){
alert(window.color); // Output=>blue window
alert(this.color); // Output=>blue window , this
alert(color); // Output=>blue this, , ,
})();
// , : window!
上の詳細例を通して、きっと分かります.以上に間違いがあれば、ご叱正をお願いします.