자바스크립트 시리즈의 심층적 이해(12) 가변 객체(Variable Object)_javascript 스킬
JavaScript를 프로그래밍할 때 시스템을 성공적으로 구축하기 위해서는 함수와 변수 선언을 피할 수 없지만, 인터프리터는 이러한 함수와 변수를 어떻게, 어디서 찾을 수 있을까요? 이러한 객체를 참조하면 정확히 어떤 일이 발생합니까?
원본 출시: Dmitry A. Soshnikov
게시 시간: 2009-06-27
러시아어 주소: http://dmitrysoshnikov.com/ecmascript/ru-chapter-2-variable-object/
영어 번역: Dmitry A. Soshnikov
출시 시간: 2010-03-15
영어 주소: http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/
일부 번역이 어려움 문장은 justinw의 중국어 번역을 나타냅니다.
대부분의 ECMAScript 프로그래머는 변수가 실행 컨텍스트와 밀접하게 관련되어 있다는 것을 알아야 합니다.
var a = 10; // 전역 컨텍스트의 변수
(function () {
var b = 20; // 전역 컨텍스트의 지역 변수 function context
})();
alert(a); // 10
alert(b); // 전역 변수 "b"가 선언되지 않았습니다.
많은 프로그래머 우리 모두 알고 있듯이 현재 ECMAScript 사양에서는 "함수" 코드 유형의 실행 컨텍스트를 통해서만 독립적인 범위를 생성할 수 있다고 명시하고 있습니다. 즉, C/C와 비교하여 ECMAScript의 for 루프는 로컬 컨텍스트를 생성할 수 없습니다.
for (var k in {a: 1 , b: 2}) {
alert(k);
}
alert(k); // 루프가 종료되었지만 변수 k는 여전히 현재 범위에 있습니다.
보자 데이터를 선언하면서 어떤 내용을 발견했는지 살펴보겠습니다.
데이터 선언
변수가 실행 컨텍스트와 관련된 경우 변수 자체는 데이터가 저장되는 위치와 액세스 방법을 알아야 합니다. 이 메커니즘을 변수 개체라고 합니다.
Variable 객체(VO로 약칭)는 실행 컨텍스트와 관련된 특수 객체입니다.
Variable(var, 변수 선언)
FunctionDeclaration(FunctionDeclaration, 약칭); FD);
함수의 형식적 매개변수
예를 들어, 일반 ECMAScript 객체를 사용하여 변수 객체를 나타낼 수 있습니다:
VO = {}
앞서 말했듯이 VO는 실행 컨텍스트의 속성입니다.
activeExecutionContext = {
VO : {
//컨텍스트 데이터(var, FD, 함수 인수)
}
}
전역 컨텍스트 변수 개체만 VO 속성 이름을 전달하여 간접적으로 액세스할 수 있습니다. (왜냐하면 전역 컨텍스트에서는 전역 객체 자체가 변수 객체이기 때문에 나중에 자세히 소개하겠습니다.) VO 객체는 내부 메커니즘의 구현일 뿐이므로 다른 컨텍스트에서 직접 액세스할 수 없습니다.
변수나 함수를 선언할 때는 VO의 새 속성을 생성할 때와 별 차이가 없습니다(예: 이름과 해당 값이 있음).
예:
var a = 10;
function test(x) {
var b = 20;
}
test(30)
해당 변수 개체는 다음과 같습니다.
VO(globalContext ) = {
a: 10,
test: <함수 참조>
}
// 테스트 함수 컨텍스트의 변수 개체
VO(test functionContext) = {
x: 30,
b: 20
};
다른 실행 컨텍스트의 변수 개체
모든 유형의 실행 컨텍스트에 대해 변수 개체 일부 작업(예: 변수 초기화) 및 동작이 일반적입니다. 이러한 관점에서 변수 객체를 추상적인 기본 것으로 이해하고 함수의 맥락에서 변수 객체와 관련된 추가 내용을 정의하는 것이 더 쉽습니다. 🎜>코드 복사
추상 변수 객체 VO(변수 초기화 프로세스의 일반적인 동작)
║
╠==> 전역 컨텍스트 변수 객체 GlobalContextVO
║ (VO === this === 전역)
║
╚==> 함수 컨텍스트 변수 객체 FunctionContextVO
(VO === AO, <인수> 및 <형식 매개변수> 추가)
자세히 살펴보세요:
전역 컨텍스트의 변수 객체
먼저 전역 객체에 명확한 정의를 제공해야 합니다.
전역 객체(전역 객체)는 실행 컨텍스트 객체에 들어가기 전에 생성됩니다.
이 개체의 복사본은 하나만 있고 해당 속성은 프로그램 어디에서나 액세스할 수 있으며 전역 개체의 수명 주기는 프로그램이 종료되는 순간 종료됩니다.
코드 복사
전역 객체의 초기 생성 단계에서는 Math, String, Date,parseInt가 자체 속성으로 사용되며 다른 속성도 속성으로 생성될 수 있습니다. 전역 객체 자체를 가리킬 수 있습니다). 예를 들어 DOM에서 전역 객체의 window 속성은 전역 객체 자체를 참조할 수 있습니다(물론 모든 특정 구현이 이와 같은 것은 아닙니다).
global = {
Math: <...>,
String: <... .>
...
...
window: global //참조 자체
}
속성에 접근할 때 접두사는 일반적으로 무시됩니다. 전역 객체는 이름으로 직접 접근할 수 없기 때문입니다. 그러나 우리는 여전히 전역 컨텍스트를 통해 전역 객체에 접근할 수 있고, 재귀적으로 그 자체를 참조할 수도 있습니다. 예를 들어 DOM의 창입니다. 요약하면 코드는 다음과 같이 축약될 수 있습니다.
String( 10); // global.String(10);
// 접두사
window.a = 10; // === global.window.a === global.a = 10 ;
this.b = 20; // global.b = 20;
전역 컨텍스트의 변수 개체로 돌아가서 이 경우 변수는 object는 전역 객체 그 자체입니다:
VO(globalContext) === global;
이 원칙을 바탕으로 전역 컨텍스트에서 대응 관계가 선언된 경우에만 위의 결론을 이해하는 것이 매우 필요합니다. 전역 개체의 속성을 통해 간접적으로 액세스합니다(예를 들어 변수 이름을 미리 알 수 없음).
var a = new String('test' );
alert(a); // VO(globalContext): "test"에서 발견됨
alert(window['a']) // 전역을 통한 간접 액세스: global === VO (globalContext) ): "test"
alert(a === this.a); // true
var aKey = 'a'
alert(window[aKey]); 동적 속성 이름 액세스: "test"
함수 컨텍스트의 변수 개체
함수 실행 컨텍스트에서는 VO에 직접 액세스할 수 없습니다. 이때 활성화 개체( 약칭 AO) VO의 역할.
VO(functionContext) === AO;
함수 컨텍스트에 진입하면 활성 객체가 생성되며, 함수의 인수 속성을 통해 초기화됩니다. Arguments 속성의 값은 Arguments 객체입니다:
AO = {
arguments:
};
Arguments 개체는 다음 특성을 포함하는 활성 개체의 특성입니다.
callee — 현재 함수에 대한 참조
length — 실제로 전달된 매개변수의 수
properties-indexes(문자열 유형의 정수) 속성 값은 함수의 매개변수 값입니다(매개변수에서 왼쪽에서 오른쪽으로 정렬됨). 목록). Properties-indexes 내부의 요소 수는 Argument.length와 동일합니다. Properties-indexes의 값은 실제로 전달된 매개변수와 공유됩니다.
예:
function foo(x, y, z) {
// 선언된 함수 매개변수 인수 수(x, y, z)
alert(foo.length) // 3
// 실제로 전달된 매개변수의 수(x, y만)
alert(arguments.length) // 2
// 매개변수의 호출 수신자는 함수 자체입니다.
alert(arguments.callee === foo); // true
// 매개변수 공유
alert(x === 인수[0]) // true
alert(x) // 10개
인수[ 0] = 20;
alert(x); // 20
x = 30;
alert(arguments[0]) // 30
// 전달된 매개변수 3번째 인덱스 값은 공유되지 않습니다.
z = 40;
alert(arguments[2]) // 정의되지 않음
arguments[2] = 50; / 40
}
foo(10, 20);
컨텍스트 코드 처리의 두 단계
이제 드디어 이 글의 핵심에 도달했습니다. 실행 컨텍스트 코드는 처리를 위해 두 가지 기본 단계로 구분됩니다.
실행 컨텍스트 입력
코드 실행
변수 개체의 수정은 이 두 단계와 밀접하게 관련되어 있습니다.
참고: 이 두 단계의 처리는 일반적인 동작이며 컨텍스트 유형과 관련이 없습니다(즉, 성능은 전역 컨텍스트와 기능 컨텍스트에서 동일합니다).
실행 컨텍스트 입력
실행 컨텍스트에 들어갈 때(코드 실행 전) VO에는 이미 다음 속성이 포함되어 있습니다(앞서 언급한 바와 같이):
함수의 모든 형식 매개변수(함수 실행에 있는 경우) context Medium)
- 이름과 해당 값으로 구성된 변수 개체의 속성이 생성되며, 해당 매개 변수가 전달되지 않으면 이름과 정의되지 않은 값으로 구성된 변수 개체의 속성도 생성됩니다.
모든 함수 선언(FunctionDeclaration, FD)
- 이름과 해당 값으로 구성된 변수 개체의 속성(함수-객체)이 생성됩니다. 변수 개체에 이미 동일한 이름의 속성이 있는 경우 이 속성을 완전히 대체합니다.
모든 변수 선언(var, VariableDeclaration)
- 변수 이름이 선언된 형식 매개변수 또는 함수와 동일한 경우 이름과 해당 값(정의되지 않음)으로 구성된 변수 개체의 속성이 생성됩니다. 변수 선언은 이 유형의 기존 속성을 방해하지 않습니다.
예제를 살펴보겠습니다.
var c = 10;
function d() {}
var e = function _e() {}
(function x() {});
}
test(10); //
호출
a: 10,
b: 정의되지 않음,
c : 정의되지 않음,
d:
e: 정의되지 않음
};
이후에는 컨텍스트 코드 처리의 두 번째 단계인 코드 실행에 들어갑니다.
코드 실행
이 주기 동안 AO/VO에는 이미 속성이 있습니다(단, 모든 속성에 값이 있는 것은 아니며 대부분의 속성 값은 여전히 시스템 기본 초기 값인 정의되지 않음).
이전 예에서도 코드 해석 중에 AO/VO가 다음과 같이 수정되었습니다.
AO['e'] =
또 다른 전형적인 예:
alert(x); // 함수
var x = 10;
alert(x); // 10
x = 20;
alert(x); // 20
// var x = 10>// 함수 "x"가 선언되지 않은 경우 >// 이때 "x"의 값은 정의되지 않아야 합니다
// 그러나 이 경우 변수 선언은 같은 이름을 가진 함수의 값에 영향을 미치지 않습니다
VO['x'] = < ;값은 방해받지 않고 여전히 작동합니다>
다음으로, 코드 실행 단계에서 VO는 다음과 같이 수정합니다:
코드
아래 예에서는 컨텍스트 단계에서 변수가 VO에 입력되는 것을 다시 볼 수 있습니다. (코드의 else 부분은 절대 실행되지 않지만 어쨌든 변수 "b"는 VO에 여전히 존재하기 때문입니다.)
코드 복사
변수에 대하여
일반적으로 JavaScript와 관련된 다양한 기사에서는 "var 키워드를 사용하든(전역 컨텍스트에서) var 키워드를 사용하지 않든(어디서든) 변수를 선언할 수 있습니다."라고 주장합니다. 이는 오해입니다.
언제든지 변수는 var 키워드를 사용해서만 선언할 수 있습니다.
위 할당문:
a = 10;
이는 전역 개체에 대한 새 속성을 생성할 뿐입니다(변수는 아님). "변수가 아니다"는 것은 변경할 수 없다는 뜻이 아니라, ECMAScript 명세의 변수 개념에 맞지 않는다는 뜻이므로 "변수가 아니다"(전역객체의 속성이 될 수 있는 이유) 이는 전적으로 VO(globalContext) = == global 때문입니다. 아직도 기억하시나요?
코드 복사
코드는 다음과 같습니다.모든 루트는 여전히 VO이고 컨텍스트 단계 및 코드 실행 단계에 들어갑니다.
코드 복사
코드는 다음과 같습니다.
코드 복사
코드는 다음과 같습니다.
코드 복사
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
- 10.1.3 – Variable Instantiation;
- 10.1.5 – Global Object;
- 10.1.6 – Activation Object;
- 10.1.8 – Arguments Object.

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Object에서 byte로, byte에서 Object로 오늘은 Object에서 byte로 변환하는 방법과 byte에서 Object로 변환하는 방법을 알아보겠습니다. 먼저 학생 클래스를 정의합니다. packagecom.byteToObject;importjava.io.Serialized;publicclassstudentimplementsSerialized{privateintsid;privateStringname;publicintgetSid(){returnsid;}publicvoidsetSid(in

1. Object 클래스 소개 Object는 Java에서 기본적으로 제공하는 클래스입니다. Object 클래스를 제외한 Java의 모든 클래스는 상속 관계를 갖습니다. 기본적으로 Object 상위 클래스를 상속합니다. 즉, Object의 참조를 이용하여 모든 클래스의 객체를 받을 수 있습니다. 예: Object를 사용하여 모든 클래스의 객체 수신 classPerson{}classStudent{}publicclassTest{publicstaticvoidmain(String[]args){function(newPerson());function(newStudent());}public

PHP 개발자의 경우 "정의되지 않은 변수" 경고 메시지가 나타나는 것은 매우 흔한 일입니다. 이 상황은 일반적으로 정의되지 않은 변수를 사용하려고 할 때 발생하며 이로 인해 PHP 스크립트가 정상적으로 실행되지 않습니다. 이 기사에서는 "PHPNotice:Undefinevariable: in Solution" 문제를 해결하는 방법을 소개합니다. 문제 원인: PHP 스크립트에서 변수가 초기화되지 않거나 값이 할당되지 않으면 "Un

PHP알림: 비개체 솔루션을 얻으려는 중 PHP에서 개발할 때 "알림: 비개체의 속성을 얻으려는 중"이라는 오류 메시지가 나타날 수 있습니다. 이 오류 메시지는 일반적으로 초기화되지 않은 개체를 사용하거나 개체가 참조를 잃어버렸기 때문에 발생합니다. 특정 코드 부분에서 속성에 올바르게 액세스할 수 없습니다.

PHP 공지 사항에 대한 해결 방법: 비객체 속성을 얻으려는 중 PHP에서 코드를 작성하는 과정에서 "비객체 속성을 얻으려는 중"이라는 오류 메시지가 나타날 수 있습니다. 이 오류 메시지는 일반적으로 존재하지 않는 개체 속성에 액세스하려고 하여 코드에 오류가 발생하기 때문에 발생합니다. 이 오류 메시지는 일반적으로 다음 상황에서 나타납니다. 개체가 존재하지 않습니다.

Java는 Object 클래스의 getClass() 함수를 사용하여 객체의 런타임 클래스를 얻습니다. Java에서 각 객체에는 객체의 속성과 메서드를 정의하는 클래스가 있습니다. getClass() 함수를 사용하여 객체의 런타임 클래스를 가져올 수 있습니다. getClass() 함수는 Object 클래스의 멤버 함수이므로 모든 Java 객체가 이 함수를 호출할 수 있습니다. 이 기사에서는 getClass() 함수를 사용하는 방법을 소개하고 몇 가지 코드 예제를 제공합니다. get을 사용하세요

1.equals 메소드 == 연산자 기본 타입과 참조 타입을 모두 결정할 수 있는 비교 연산자. 기본 타입이 결정되면 값이 동일한지 여부를 결정합니다. 주소가 동일한지, 즉 동일한 객체인지 여부는 객체 클래스의 메서드이며 참조 유형 객체 동일 소스 코드만 확인할 수 있습니다. publicbooleanequals(Objectobj){return(this==obj); } 객체 클래스의 equals 메소드는 객체의 주소가 동일한지(동일한 객체인지) 여부를 결정하는 것이지만 다른 데이터 유형 클래스는 다음과 같이 equals 메소드를 재정의한다는 것을 분명히 볼 수 있습니다.

기본 데이터 유형과 Object 사이의 관계 Object가 모든 유형의 기본 클래스라는 것을 누구나 들어봤을 것입니다. 그러나 이 문장은 실제로 정확하지 않습니다. 왜냐하면 Java의 기본 데이터 유형은 Object와 관련이 없기 때문입니다. 예를 들어 swap 메소드를 호출할 때 실제로 Object는 기본 데이터 유형과 아무 관련이 없기 때문에 int 유형을 swap(Objectobj) 메소드에 직접 전달할 수 없습니다. 이제 자동으로 Wrapping하게 되어 Integer 타입이 되었고, 기본 데이터 타입의 래퍼 클래스인 Swap 메소드를 성공적으로 호출할 수 있게 되었습니다.
