코드 복사 코드는 다음과 같습니다.
alert(x); // 함수
var x = 10;
alert(x); // 10
x = 20;
alert(x); // 20
첫 번째 경고 "x"의 반환 값이 함수이고 "x"가 선언되기 전에 "x"에 액세스하는 이유는 무엇입니까? 왜 10이나 20이 아닌가? 사양에 따르면 함수 선언은 순환에 동의하여 컨텍스트에 들어갈 때 채워지기 때문에 컨텍스트에 들어갈 때 변수 선언 "x"도 있고 이전 단계에서 말했듯이 변수 선언이 따릅니다. 순차적으로 함수 선언 및 형식 매개변수 선언 후, 이 컨텍스트 진입 단계에서 변수 선언은 VO에 이미 존재하는 동일한 이름의 함수 선언 또는 형식 매개변수 선언을 방해하지 않습니다. VO의 구조는 다음과 같습니다.
VO = {}; VO['x'] = < FunctionDeclaration "x"에 대한 참조>
// var x = 10>// 함수 "x"가 선언되지 않은 경우 >// 이때 "x"의 값은 정의되지 않아야 합니다
// 그러나 이 경우 변수 선언은 같은 이름을 가진 함수의 값에 영향을 미치지 않습니다
VO['x'] = < ;값은 방해받지 않고 여전히 작동합니다>
다음으로, 코드 실행 단계에서 VO는 다음과 같이 수정합니다:
코드
두 번째와 세 번째 알림에서 이러한 효과를 확인할 수 있습니다.
아래 예에서는 컨텍스트 단계에서 변수가 VO에 입력되는 것을 다시 볼 수 있습니다. (코드의 else 부분은 절대 실행되지 않지만 어쨌든 변수 "b"는 VO에 여전히 존재하기 때문입니다.)
코드 복사
var b = 2; 🎜>alert(a); // 1
alert(b); // 정의되지 않음, b가 선언되지 않은 것이 아니라 b의 값이 정의되지 않음
변수에 대하여
일반적으로 JavaScript와 관련된 다양한 기사에서는 "var 키워드를 사용하든(전역 컨텍스트에서) var 키워드를 사용하지 않든(어디서든) 변수를 선언할 수 있습니다."라고 주장합니다. 이는 오해입니다.
언제든지 변수는 var 키워드를 사용해서만 선언할 수 있습니다.
위 할당문:
a = 10;
이는 전역 개체에 대한 새 속성을 생성할 뿐입니다(변수는 아님). "변수가 아니다"는 것은 변경할 수 없다는 뜻이 아니라, ECMAScript 명세의 변수 개념에 맞지 않는다는 뜻이므로 "변수가 아니다"(전역객체의 속성이 될 수 있는 이유) 이는 전적으로 VO(globalContext) = == global 때문입니다. 아직도 기억하시나요?
다음 예시를 통해 구체적인 차이점을 살펴보겠습니다.
코드 복사
코드는 다음과 같습니다.
모든 루트는 여전히 VO이고 컨텍스트 단계 및 코드 실행 단계에 들어갑니다.
컨텍스트 단계에 들어갑니다.
코드 복사
코드는 다음과 같습니다.
VO = { a: 정의되지 않음 }; "b"가 다음과 같기 때문에 알 수 있습니다. 변수가 아닙니다. 이 단계에서는 "b"가 전혀 없습니다. "b"는 코드 실행 단계에서만 나타납니다(그러나 우리의 경우에는 그 전에 오류가 발생합니다).
예제 코드를 변경해 보겠습니다.
코드 복사
코드는 다음과 같습니다.
변수에 대한 또 다른 중요한 지식 포인트가 있습니다. 단순 속성과 비교하여 변수에는 {DontDelete} 속성이 있습니다. 이 속성의 의미는 변수 속성을 삭제 연산자를 사용하여 직접 삭제할 수 없다는 것입니다.
코드 복사
코드는 다음과 같습니다.
a = 10;
alert(window.a); // 10
alert(delete a); // true
alert(window.a); // undefined
var b = 20;
alert(window.b); // 20
alert(delete b); // false
alert(window.b); // still 20
But this rule cannot be distorted in one context, that is, the eval context, and the variable does not have the {DontDelete} attribute.
eval('var a = 10;');
alert(window.a); // 10
alert(delete a); // true
alert(window.a); // undefined
Use some debugging tools (For example: Firebug) console when testing this instance, please note that Firebug also uses eval to execute your code in the console. Therefore, variable attributes also do not have the {DontDelete} attribute and can be deleted.
Special implementation: __parent__ attribute
As mentioned before, according to the standard specification, active objects cannot be accessed directly. However, some specific implementations do not fully comply with this regulation, such as SpiderMonkey and Rhino; in the implementation, the function has a special attribute __parent__, through which the active object or global variable object that the function has created can be directly referenced.
For example (SpiderMonkey, Rhino):
var global = this;
var a = 10;
function foo() {}
alert(foo.__parent__); // global
var VO = foo.__parent__;
alert(VO. a); // 10
alert(VO === global); // true
In the above example we can see that the function foo is created in the global context, So the attribute __parent__ points to the variable object of the global context, that is, the global object.
However, it is not possible to access the active object in the same way in SpiderMonkey: in different versions of SpiderMonkey, the __parent__ of the internal function sometimes points to null and sometimes points to the global object.
In Rhino, it is completely possible to access active objects in the same way.
For example (Rhino):
var global = this ;
var x = 10;
(function foo() {
var y = 20;
// Active object in "foo" context
var AO = (function () { }).__parent__;
print(AO.y); // 20
// The __parent__ of the current active object is the existing global object
// A special chain of variable objects forms
// So we call it scope chain
print(AO.__parent__ === global); // true
print(AO.__parent__.x); // 10
})();
Summary
In this article, we took an in-depth look at objects related to execution context. I hope this knowledge can be helpful to you and solve some problems or confusions you have encountered. As planned, in subsequent chapters, we will explore scope chains, identifier resolution, and closures.
Any questions, I’d be happy to answer them in the comments below.
Other references