함수의 실행 컨텍스트는 현재 실행 환경에 따라 결정됩니다.
1. 전역 변수와 전역 함수는 전역 개체(창)에 연결되므로 "var" 또는 "this"를 사용하여 전역 변수를 정의하는 것은 동일합니다.
2. 실행 맥락과 범위가 다릅니다. 실행 컨텍스트는 런타임에 결정되고 언제든지 변경될 수 있지만 범위는 정의 시간에 결정되며 절대 변경되지 않습니다.
3. 객체의 메소드가 현재 실행되고 있는 경우 실행 컨텍스트는 이 메소드가 연결된 객체입니다.
4. 현재 프로세스가 객체를 생성하거나 객체의 메소드를 실행하는 것이라면 실행 컨텍스트는 생성되는 객체입니다.
5. 메소드 실행 시 첨부된 객체를 명시적으로 지정하지 않으면 이 메소드의 컨텍스트는 전역 객체입니다.
6. 호출 및 적용을 사용하여 개체의 실행 컨텍스트를 변경합니다. " 전역 변수"; //전역 변수가 개체에 연결됩니다.
//this.v1 = "전역 변수 with this"; //전역 변수가 정의되면 var v1과 this.v1의 두 메서드는 동일합니다. .
function func1(){
func1에 전역 객체와 이름이 같은 v1 변수가 있으므로 func1에서 v1에 대한 직접 참조는 func1에 정의된 변수를 참조합니다. . JavaScript에는 전역 변수를 숨기는 지역 변수 기능도 있습니다. 그러나 func1은 연결된 객체를 명시적으로 지정하지 않으므로 실행 컨텍스트는 전역 객체이고 이를 사용하여 참조되는 변수는 전역 변수입니다.
약간 더 복잡한 예를 살펴보세요.
코드 복사
코드는 다음과 같습니다.
function ftest(){
var v = "v1v1v1";
this.this_v = "this_v";
return function(){
ftest가 함수로 실행될 때 컨텍스트는 전역 객체입니다. 따라서 ftest에서 이를 사용하여 정의된 변수는 전역 변수가 됩니다. 따라서 ftest 외부에서 this_v 값에 액세스하기 위해 변수 이름을 직접 사용합니다. 그러나 ftest에서 반환된 익명 함수는 ftest 내부에 정의되어 있으므로 이 익명 함수의 범위는 ftest 내부에 있습니다. 따라서 동일한 이름의 전역 변수 v와 지역 변수 v가 있는 경우 이 익명 함수는 ftest 내부에 정의된 변수 v에 액세스합니다.
다음으로 ftest를 클래스로 처리하고 새 키워드를 사용하여 인스턴스화합니다.
코드 복사
코드는 다음과 같습니다. :
function ftest(){
var v = "v1v1v1";
this.this_v = "this_v"
return function(){
writeHtml(v );
writeHtml(this.this_v);
ftest를 객체로 인스턴스화하면 객체 생성 과정에서 컨텍스트가 생성됩니다. 그 자체. 이때 생성된 객체는 ftest의 인스턴스이며, 생성이 완료된 후 함수가 반환된다는 점에 유의하세요. 이로 인해 new ftest()는 ftest( 인스턴스화 후 객체에 대한 참조가 아닌 인스턴스화 후 함수를 반환하게 됩니다. ). 따라서 이 인스턴스화된 개체는 참조될 수 없습니다. 반환된 함수를 정의할 때 이 함수의 컨텍스트는 this로 지정되지 않기 때문에 반환된 함수의 컨텍스트는 전역 개체이고 범위는 ftest() 함수 내부에 있습니다. 따라서 a() 함수가 실행되면 this_v 변수가 컨텍스트에 정의되지 않아 접근 오류가 발생합니다.
참고로 위 코드는
코드 복사
코드는 다음과 같습니다.
function ftest( ){
return function(){
}
}
이 형식은 정적 캡슐화 환경이 아닙니다. 정적 캡슐화 환경은 다음과 같아야 합니다. 함수 정의가 완료되었습니다. 실행하고, 실행이 완료된 후 함수에 내부 함수를 반환합니다.
다음 예를 통해 범위와 컨텍스트가 변수 참조에 미치는 영향을 살펴보겠습니다.
코드 복사
코드는 다음과 같습니다.
var v = "전역 변수";
function method(){
writeHtml(v)
writeHtml(this.v);
}
var Class1 = function(){
var v = "개인 변수";
this.v = "객체 변수";
var method2 = 메소드
this.method2 = 메소드;
var method3 = function(){
writeHtml(v);
writeHtml(this.v)
}
this.method3 = function(){
writeHtml(v) ;
writeHtml(this.v);
}
method2(); //전역 변수
//전역 변수
전역 변수
//객체 변수
method3(); //전용 변수
//전역 변수
this.method3();//전용 변수
//객체 변수
}
var obj = new Class1();
메서드는 전역적으로 정의되므로 정의 시 메소드의 범위가 전역으로 결정됩니다. 따라서 Class1 내에서 method2가 호출되면 해당 범위는 전역이고 컨텍스트는 전역 개체입니다. 따라서 함수에서 액세스되는 변수는 전역 변수입니다.
마찬가지로 this.method2가 호출되면 범위는 전역이지만 컨텍스트가 Class1인 객체를 나타내기 위해 정의될 때 함수는 this 키워드를 사용하기 때문에 함수는 전역에 액세스할 때 컨텍스트 한정 없이 변수에 액세스합니다. 변수, 컨텍스트 제한 변수에 액세스하면 현재 컨텍스트의 해당 변수에 액세스합니다.
method3과 this.method3을 호출할 때, 지역 변수는 전역 변수를 숨기므로 컨텍스트 없이 변수에 접근할 때 지역 변수에 접근합니다. context 제한이 있는 경우 방법 2와 동일하며 현재 context에 있는 변수에 접근한다.
call과 Apply를 사용하면 실행 컨텍스트가 변경될 수 있습니다. call과 Apply에는 서로 다른 매개변수 유형만 있으므로 다음 예에서는 설명하기 위해 call을 사용합니다.
var v = "global Variable"
var method = function(){
writeHtml(this.v);
}
var Class2 = function(){
this.v = "Class2 인스턴스의 객체 변수"; 🎜>this .method = function(){
writeHtml(this.v);
}
}
var Class3 = function(){
this.v = "인스턴스의 객체 변수 of Class3" ;
this.method = function(){
writeHtml(this.v);
}
}
var obj2 = new Class2();
var obj3 = new Class3();
method(); //전역 변수
obj2.method(); //Class2 인스턴스의 객체 변수
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를 사용하여 지정된 컨텍스트에 메서드를 바인딩할 수 있습니다. 전역 환경에서 이것이 가리키는 컨텍스트는 전역 개체입니다.