関数の実行コンテキストは、現在の実行環境によって決まります:
1. グローバル変数とグローバル関数はグローバル オブジェクト (ウィンドウ) にアタッチされるため、「var」または「this」を使用してグローバル変数を定義することは同等です。
2. 実行コンテキストとスコープが異なります。実行コンテキストは実行時に決定され、いつでも変更される可能性がありますが、スコープは定義時に決定され、決して変更されません。
3. オブジェクトのメソッドが現在実行されている場合、実行コンテキストはこのメソッドが関連付けられているオブジェクトです。
4. 現在のプロセスがオブジェクトを作成するか、オブジェクトのメソッドを実行する場合、実行コンテキストは作成されるオブジェクトです。
5. メソッドの実行時に添付オブジェクトを明示的に指定しない場合、このメソッドのコンテキストはグローバル オブジェクトです。
6. call と apply を使用して、オブジェクトの実行コンテキストを変更します。 " global variable"; // グローバル変数はオブジェクトにアタッチされます
//this.v1 = "global variable with this" // グローバル変数が定義されている場合、2 つのメソッド var v1 と this.v1 は同等です。 。
function func1(){
var v1 = "パート変数";
writeHtml(this.v1); func1(); part 変数 //グローバル変数 func1 にはグローバル オブジェクトと同じ名前の v1 変数があるため、func1 内の v1 への直接参照は func1 で定義された変数を参照します。 。 JavaScript には、グローバル変数を隠すローカル変数という機能もあります。ただし、func1 はアタッチされたオブジェクトを明示的に指定していないため、その実行コンテキストはグローバル オブジェクトであり、これを使用して参照される変数はグローバル変数です。
もう少し複雑な例を見てください:
コードをコピーします
コードは次のとおりです:
function ftest(){
var v = "v1v1v1";
this.this_v = "this_v";
return function(){
writeHtml(v); this.this_v );
ftest が関数として実行される場合、コンテキストはグローバル オブジェクトです。したがって、ftest でこれを使用して定義された変数はグローバル変数になります。したがって、変数名を直接使用して、ftest の外部で this_v の値にアクセスします。ただし、ftest で返される匿名関数は ftest 内で定義されているため、この匿名関数のスコープは ftest 内になります。したがって、同名のグローバル変数 v とローカル変数 v が存在する場合、この無名関数は ftest の内部で定義されている変数 v にアクセスします。
次に、ftest をクラスとして扱い、新しいキーワードを使用してインスタンス化します。
コードをコピーします
コードは次のとおりです。 :
function ftest(){
var v = "v1v1v1";
return function(){
writeHtml(v) );
writeHtml(this.this_v);
}
}
var a = new ftest();
var v = "v2v2v2"; ; // エラー :this_v unknown
a(); //v1v1v1 //unknown ftest をオブジェクトとしてインスタンス化する場合、オブジェクトの作成プロセス中にコンテキストが作成されます。自体。このとき作成されるオブジェクトは ftest のインスタンスであり、作成完了後に関数が返されるため、 new ftest() は ftest( のインスタンス化後のオブジェクトへの参照ではなく、インスタンス化後の関数を返すことになります。) )。したがって、このインスタンス化されたオブジェクトを参照することはできません。返される関数を定義するとき、この関数のコンテキストは this で指定されていないため、返される関数のコンテキストはグローバル オブジェクトとなり、スコープは ftest() 関数内になります。したがって、関数 a() を実行すると、コンテキストに this_v 変数が定義されていないため、アクセス エラーが発生します。 上記のコードに注意してください:
コードをコピーします
コードは次のとおりです:
function ftest( ){
return function(){
}
}
この形式は静的カプセル化環境ではありません。静的カプセル化環境は次のようにする必要があります。関数の定義が完了しました 実行し、実行完了後に関数内で内部関数を返します。
次の例を見て、変数参照に対するスコープとコンテキストの影響を観察してみましょう。
コードをコピー コードは次のとおりです:
var v = "グローバル変数";
関数メソッド(){
writeHtml(this.v);
var Class1 = function(){
var v = "プライベート変数";
var メソッド 2 = メソッド;
var method3 = function(){
writeHtml(v);
writeHtml(this.v)
}
this.method3 = function(){
writeHtml(v); ;
writeHtml(this.v);
method2(); // グローバル変数
// グローバル変数
//オブジェクト変数
method3(); //プライベート変数
//グローバル変数
this.method3();//プライベート変数
//オブジェクト変数
}
var obj = new Class1();
メソッドはグローバルに定義されているため、メソッドのスコープは定義時にグローバルに決定されます。したがって、Method2 が Class1 内で呼び出される場合、そのスコープはグローバルであり、コンテキストはグローバル オブジェクトになります。したがって、関数内でアクセスされる変数はグローバル変数です。
同様に、this.method2 が呼び出されるとき、そのスコープはグローバルですが、関数がコンテキストが Class1 であるオブジェクトを示すために定義されているときに this キーワードを使用するため、関数はグローバルにアクセスするときにコンテキスト修飾なしで変数にアクセスします。変数の場合、コンテキスト限定変数にアクセスすると、現在のコンテキスト内の対応する変数にアクセスします。
method3 と this.method3 を呼び出すと、ローカル変数はグローバル変数を隠すため、コンテキストなしで変数にアクセスするときにローカル変数にアクセスします。コンテキスト制限がある場合は方法2と同様で、現在のコンテキスト内の変数にアクセスします。
call と apply を使用すると、実行コンテキストを変更できます。call と apply はパラメーターの型が異なるだけであるため、次の例では説明のために call を使用します。
コードをコピーします
コードは次のとおりです。
writeHtml(this.v);
}
}
var Class3 = function(){
this.v = "インスタンス内のオブジェクト変数Class3" ;
this.method = function(){
writeHtml(this.v);
}
}
var obj2 = new Class2();
var obj3 = new Class3();
method(); // グローバル変数
obj2.method(); // クラス 2 のオブジェクト変数
obj3.method(); Class3 のインスタンスのオブジェクト変数
method.call(obj2); //Class2 のインスタンスのオブジェクト変数
method.call(obj3); //Class3 のインスタンスのオブジェクト変数
obj2. method.call (obj3); //Class3 のインスタンスのオブジェクト変数
obj2.method.call(this); //グローバル変数
obj3.method.call(obj2); Class2
obj3.method.call(this); //グローバル変数
ご覧のとおり、call または apply を使用してメソッドを指定されたコンテキストにバインドできます。グローバル環境では、this が指すコンテキストがグローバル オブジェクトです。