정의에서 실행에 이르기까지 JS 엔진은 구현 계층에서 많은 초기화 작업을 수행합니다. 따라서 JS 엔진의 작업 메커니즘을 배우기 전에 실행 환경 스택, 글로벌 객체, 실행 환경, 가변 객체, 활성 객체, 범위 및 범위 체인 등의 몇 가지 관련 개념을 소개해야합니다. 이러한 개념은 JS 엔진의 작업의 핵심 구성 요소입니다. 이 기사의 목적은 각 개념을 분리하여 설명하는 것이 아니라 간단한 데모를 통해이를 분석하여 정의에서 실행에 이르기까지 JS 엔진의 세부 사항과 이러한 개념이 수행하는 역할을 설명하는 것입니다.
var x = 1; // 전역 변수 정의 xfunction a (y) {var x = 2; // 로컬 변수 정의 X 함수 b (z) {// 내부 함수 정의 b console.log (x+y+z); } 반환 b; // 기능 b} var c = a (1)에 대한 참조를 반환합니다. // a, return bc (1); // 함수 실행 b이 데모는 폐쇄이며 실행 결과는 4입니다. 아래에서는 3 단계로 JS 엔진의 작동 메커니즘을 분석합니다 : 글로벌 초기화, 실행 함수 A 및 실행 기능 B :
1. 글로벌 초기화
JS 엔진이 실행 가능한 코드를 입력하면 다음 세 가지 초기화 작업을 완료해야합니다.
먼저 글로벌 객체 (글로벌 객체)를 만듭니다. 이 객체의 전역 사본은 하나 뿐이며, 그 속성은 어디서나 액세스 할 수 있으며 그 존재는 응용 프로그램의 전체 수명주기와 함께 제공됩니다. 전역 객체를 만들 때 일반적으로 사용되는 JS 개체는 수학, 문자열, 날짜, 문서가 속성으로 사용됩니다. 이 글로벌 객체는 이름으로 직접 액세스 할 수 없으므로 다른 속성 창이 있으며 창 자체를 가리므로 전역 객체에 창을 통해 액세스 할 수 있습니다. 전역 객체를 시뮬레이션하기 위해 의사 코드를 사용하는 일반적인 구조는 다음과 같습니다.
// 글로벌 객체 생성 var globalObject = {math : {}, 문자열 : {}, date : {}, document : {}, // dom 작동 ... 창 :이 // 창 속성이 자체를 가리 킵니다}그런 다음 JS 엔진은 실행 컨텍스트 스택을 구축해야합니다. 동시에, 글로벌 실행 컨텍스트 EC를 생성 하고이 글로벌 실행 환경 EC를 실행 환경 스택으로 푸시해야합니다. 실행 환경 스택의 기능은 프로그램을 올바른 순서로 실행할 수 있도록하는 것입니다. JavaScript에서는 각 기능에는 자체 실행 환경이 있습니다. 함수를 실행할 때 함수의 실행 환경이 실행 환경 스택의 상단으로 밀려 나고 실행 권한을 얻습니다. 이 함수가 실행되면 실행 환경이 스택 상단에서 삭제되고 실행 권한이 이전 실행 환경으로 반환됩니다. Pseudocode를 사용하여 실행 환경 스택과 EC의 관계를 시뮬레이션합니다.
var ecstack = []; // 배열 var ec = {}과 유사한 실행 환경 스택 정의; // 실행 공간 생성 // ECMA-262 사양은 EC의 데이터 구조를 명확하게 정의하지 않으며, 메모리 ecstack.push (EC)에 할당 된 공간으로 이해할 수 있습니다. // 함수를 입력하고 실행 환경 ecstack.pop (EC); // 함수가 반환 된 후 실행 환경을 삭제하십시오마지막으로, JS 엔진은 또한 EC와 관련된 전역 변수 객체 (Varibale Object) VO를 생성하고 Global Object를 가리 킵니다. VO에는 글로벌 객체의 원래 특성이 포함될뿐만 아니라 변수 x와 전역으로 정의 된 기능을 포함합니다. 동시에 함수 a를 정의 할 때 내부 속성 범위도 A에 추가되고 VO에 포인트 범위가 추가됩니다. 각 함수가 정의되면 이와 관련된 범위 속성이 생성되며 범위는 항상 함수가 정의되는 환경을 가리 킵니다. 이 시점의 황후 구조는 다음과 같습니다.
ecstack = [// 실행 환경 스택 EC (g) = {// 글로벌 실행 환경 VO (g) : {// 글로벌 객체의 원래 속성을 포함합니다 x = 1; // 변수 정의 x a = function () {...}; // 함수 정의 aa [[scope]] = this; // a의 범위를 정의하고 vo 자체에 값을 할당}}];2. 실행 함수 a
실행이 A (1)에 들어가면 JS 엔진은 다음을 수행해야합니다.
먼저, JS 엔진은 기능 A의 실행 환경 EC를 생성 한 다음 EC는 실행 환경 스택의 상단으로 밀어서 실행 권한을 얻습니다. 현재 실행 환경 스택에는 두 가지 실행 환경, 즉 글로벌 실행 환경과 기능 A 실행 환경이 있습니다. A의 실행 환경은 스택의 상단에 있으며 전역 실행 환경은 스택의 하단에 있습니다. 그런 다음 기능 A의 범위 체인을 만듭니다. JavaScript에서 각 실행 환경에는 식별자 해상도를위한 자체 스코프 체인이 있습니다. 실행 환경이 생성되면 스코프 체인은 현재 실행중인 함수의 범위에 포함 된 객체로 초기화됩니다.
다음으로 JS 엔진은 현재 함수의 활성 객체 (활성화 객체) AO를 생성합니다. 여기서 활성 객체는 가변 객체의 역할을 수행하지만 함수에서 다르게 호출됩니다 (변수 객체가 일반적인 개념이며 활성 객체는 그 분기라고 생각할 수 있습니다). AO에는 함수의 공식 매개 변수, 인수 객체,이 객체 및 로컬 변수 및 내부 함수의 정의가 포함되면 AO는 스코프 체인의 상단으로 밀려납니다. 함수 B를 정의 할 때 JS 엔진은 B에 범위 속성을 추가하고 기능 B가 정의 된 환경에 포인트 범위를 추가합니다. 함수 B가 정의 된 환경은 A의 활성 객체 AO이며 AO는 링크 된 목록의 앞쪽 끝에 있습니다. 링크 된 목록에는 최종 연결의 특성이 있으므로 함수 B의 범위는 A의 전체 범위 체인을 가리 킵니다.
ecstack = [// 실행 환경 스택 EC (a) = {// a의 실행 환경 [스코프] : VO (g), // vo는 글로벌 변수 객체 ao (a) : {// 활성 객체 생성 y : 1, x : 2, // 로컬 변수 x b : function () {... // 이것은 AO 자체를 말하고 AO는 Scopechain의 상단에 있으므로 B [Scope]] 전체 범위 체인 인수를 가리 킵니다. [], // 기능에서 우리가 액세스하는 인수는 AO의 인수입니다. window // 함수의 기능은 발신 창의}, scopechain : <a. (a), // 링크 된 목록입니다. 그런 다음 AO가 스코프 체인의 상단에 추가됩니다. 현재 A의 범위 체인 : AO (a)-> vo (g)}, ec (g) = {// 글로벌 실행 환경 VO (g) : {// 글로벌 객체 x = 1의 원래 속성을 포함합니다. // 변수를 정의합니다 x a = function () {...}; // 함수 AA [[scope]] = this; // a의 범위를 정의합니다. [[scope]] == vo (g)}}];3. 기능 실행 b
함수 A가 실행 된 후, B에 대한 참조가 반환되고 변수 C에 할당된다. C (1)의 실행은 B (1) 실행과 동일하다. JS 엔진은 다음 작업을 완료해야합니다.
먼저, 위와 마찬가지로 함수 B의 실행 환경 EC를 생성 한 다음 EC를 실행 환경 스택의 상단으로 밀고 실행 권한을 얻습니다. 현재 실행 환경 스택에는 두 가지 실행 환경, 즉 글로벌 실행 환경과 기능 B의 실행 환경이 있습니다. B의 실행 환경은 스택의 맨 위에 있으며 글로벌 실행 환경은 스택의 맨 아래에 있습니다. (참고 : 기능 A가 반환 할 때 A의 실행 환경이 스택에서 삭제되어 전역 실행 환경 만 남겨두고 함수 B의 범위 체인을 만들고 기능 B의 범위에 포함 된 객체로 초기화합니다. 현재 Ecstack은 다음과 같이됩니다.
ecstack = [// 실행 환경 스택 EC (b) = {// B의 실행 환경을 생성하고 스코프 체인의 상단에 있습니다. scopechain : <ao (b), b [[scope]]> // 링크 된 목록은 b [[scope]]로 초기화 된 다음 AO (b)가 링크 된 목록의 헤더에 추가됩니다. 현재 B의 스코프 체인 : ao (b)-> ao (a) -vo (g)}, ec (a), // a의 실행 환경이 스택 상단에서 삭제되었습니다. // 변수 정의 x a = function () {...}; // 함수 정의 aa [[scope]] = this; // a, a [[scope]] == vo (g)}}의 범위를 정의합니다.함수 B가 "x+y+z"를 실행하면 3 개의 식별자 x, y 및 z를 하나씩 구문 분석해야합니다. 구문 분석 프로세스는 변수 검색 규칙을 준수합니다. 먼저 활성 객체에 속성이 존재하는지 여부를 찾으십시오. 그것이 존재하면 검색을 중지하고 반환하십시오. 존재하지 않으면 스코프 체인을 따라 상단에서 찾을 때까지 계속 검색하십시오. 전체 스코프 체인에서 변수를 찾을 수없는 경우 "정의되지 않은"을 반환하십시오. 위의 분석에서 기능 B의 범위 체인이 다음과 같습니다.
ao (b)-> ao (a)-> vo (g)
따라서 변수 X는 AO (a)에서 찾을 수 있으며 VO (g)에서 x를 찾지 않으며 변수 y는 ao (a)에서 찾을 수 있으며 변수 z는 자체 AO (b)에서 찾을 수 있습니다. 실행 결과 : 2+1+1 = 4.
간단한 요약
JS 엔진의 작업 메커니즘을 이해 한 후에는 개념을 이해하는 수준에 머무를 수는 없지만 실제 작업에서 코드를 최적화하고 개선하고 실행 효율성을 향상 시키며 실제 값을 생성하는 기본 도구로 사용합니다. 변수 검색 메커니즘을 예로 들어보십시오. 코드가 깊게 중첩되고 전역 변수를 참조 할 때마다 JS 엔진은 전체 스코프 체인을 찾습니다. 예를 들어, 스코프 체인의 하단에있는 창과 문서 개체에는이 문제가 있습니다. 따라서이 문제에 대해 많은 성능 최적화 작업을 수행 할 수 있으며 물론 최적화의 다른 측면이 있습니다. 나는 여기에서 자세히 설명하지 않을 것입니다. 이 기사는 방금 팁 오프로 간주됩니다!
@一竞 2015 년
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.