이 기사에서는 js 엔진이 js 코드를 실행하는 방법과 관련된 문제를 주로 소개하는 javascript에 대한 관련 지식을 제공합니다. js 엔진은 js 코드를 실행할 때 위에서 아래로 어휘 분석과 문법 분석도 수행합니다. , 의미 분석 및 기타 처리를 수행하고 코드 구문 분석이 완료된 후 AST를 생성하는 것이 모든 사람에게 도움이 되기를 바랍니다.
관련 추천: javascript 튜토리얼
우리는 아마도 "실행 환경", "범위", "프로토타입(체인)", "실행 컨텍스트" 등과 같은 말을 자주 듣게 될 것입니다. 그들은 무엇을 설명합니까?
우리는 js가 약한 유형의 언어이고 변수 유형은 런타임에만 결정된다는 것을 알고 있습니다. js 엔진은 js 코드를 실행할 때 위에서 아래로 어휘 분석, 문법 분석, 의미 분석 등의 프로세스를 수행하고, 코드 분석이 완료된 후 AST(추상 구문 트리)를 생성합니다. , 그리고 마지막으로 CPU가 실행하고 실행할 수 있는 AST Machine 코드를 기반으로 생성합니다.
또한 JS 엔진은 코드를 실행할 때 다른 처리도 수행합니다. 예를 들어 V8에는 두 가지 단계가 있습니다.
이는 "실행 컨텍스트"와 "범위 체인"이라는 두 가지 개념으로 이어집니다.
위에서 우리는 알 수 있습니다: js 코드가 실행 가능한 코드 조각을 실행할 때 해당 실행 컨텍스트가 생성됩니다.
우선 js에서 실행 가능한 코드에 해당하는 개념이 있습니다: "실행 환경" - 전역 환경, 함수 환경 및 eval
.
둘째, 모든 실행 컨텍스트에는 세 가지 중요한 속성이 있습니다.
두 가지 코드를 살펴보겠습니다.
var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해="global JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해";function checkJavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해(){ var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해="local JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해"; function f(){ return JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해; } return f();}checkJavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해();
var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해="global JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해";function checkJavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해(){ var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해="local JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해"; function f(){ return JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해; } return f;}checkJavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해()();
그들은 무엇을 인쇄할 것입니까? ?
왜요? 대답은 실행 컨텍스트 스택이 다르다는 것입니다!
"실행 컨텍스트 스택"이란 무엇입니까?
실행 가능한 코드를 실행할 때 미리 준비 작업을 하게 됩니다. 여기서의 "준비 작업"을 전문적으로는 "실행 컨텍스트"라고 합니다. 그런데 함수 등 실행 가능한 코드가 늘어나는데, 이렇게 많은 실행 컨텍스트를 어떻게 관리해야 할까요? 그래서 JS 엔진은 실행 컨텍스트 스택이라는 개념을 만들었습니다.
배열을 완전히 사용하여 동작을 시뮬레이션할 수 있습니다(스택 맨 아래에는 항상 전역 실행 컨텍스트 globalContext가 있습니다)
먼저 EStack을 정의하고
EStack=[globalContext];
한 다음 첫 번째 코드 조각을 시뮬레이션합니다.
EStack.push(<checkjavascript js> functionContext);EStack.push(<f> functionContext);EStack.pop();EStack.pop();</f></checkjavascript>
그리고 두 번째 코드는 다음과 같습니다:
EStack.push(<checkjavascript js> functionContext);EStack.pop();EStack.push(<f> functionContext);EStack.pop();</f></checkjavascript>
그 이유는 "클로저" 개념을 먼저 공부해야 할 수도 있기 때문입니다!
그런데 "프론트엔드 모듈화"에서 "장기간 데이터 저장"을 어떻게 구현하나요?
캐싱? 아니요. 폐쇄!
먼저 범위는 프로그램에서 변수가 정의되는 영역을 나타냅니다. 범위는 변수를 찾는 방법을 지정하며, 이는 현재 실행 중인 코드의 변수에 대한 액세스 권한을 결정합니다.
범위에는 정적 범위와 동적 범위의 두 가지 유형이 있습니다.
JS에서 채택한 정적 범위를 "어휘 범위"라고도 합니다. 함수의 범위는 함수가 정의될 때 결정됩니다.
위에서 어휘 범위의 변수는 컴파일 과정에서 특정 범위를 갖습니다. 이 범위는 "현재 실행 컨텍스트"입니다. ES5 이후에는 실행 컨텍스트를 설명하기 위해 범위 대신 "어휘적 환경"을 사용합니다. 어휘 환경은 두 가지 구성원으로 구성됩니다.
우리는 여전히 여기에 있습니다. 예를 보세요:
var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해=1;function foo(){ console.log(JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해);}function bar(){ var JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해=2; foo();}bar();
위의 정의를 다시 보면, 무엇을 인쇄해야 할까요?
실행 과정을 분석해 보겠습니다.
foo() 함수를 실행하고 먼저 foo 함수 내부에 지역 변수 값이 있는지 검색합니다. 그렇지 않은 경우 는 정의된 위치, 즉 JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해=1을 기준으로 상위 레이어의 코드를 검색하므로 결과는 1로 인쇄됩니다.
물론 그렇게 간단하지는 않고 실행 컨텍스트 관점에서 요약할 수 있습니다.
上面我们说了词法环境(作用域)的两个组成。再结合执行上下文,我们不难发现:通过外部词法环境的引用,作用域可以顺着栈层层拓展,建立起从当前环境向外延伸的一条链式结构。
再来看一个例子:
function foo(){ console.dir(bar); var a=1; function bar(){ a=2; }}console.dir(foo);foo();
由静态作用域,全局函数foo创建了一个自身对象的 [[JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해]]
属性
foo[[JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해]]=[globalContext];
而当我们执行foo()时,也会先后进入foo函数的定义期和执行期。在foo函数的定义期时,函数bar的 [[JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해]]
将会包含全局内置JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해和foo的内置JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해
bar[[JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해]]=[fooContext,globalContext];
这证明了这一点:“JS会通过外部词法环境引用来创建变量对象的一个作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”
让我们再回头看看执行上下文中的那道题,在前面我们说了它们有什么不同,这里说下为什么它们相同地打印了“local JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해”:还是那句话“JS采用的是词法作用域,函数的作用域取决于函数创建的位置” —— JS函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해一定是指局部变量,不管何时何地执行 f() ,这种绑定在执行 f() 时依然有效。
当某个变量无法在自身词法环境记录中找到时,可以根据外部词法环境引用向外层进行寻找,直到最外层的词法环境中外部词法环境引用为null
。
与此相似的是“对象中基于原型链的查找”:
__proto__
为null)为止它们的区别也显而易见:原型链是通过 prototype 属性建立对象继承的链接;而作用域链是指内部函数能访问到外部函数的闭包。不管直接还是间接,所有函数的作用域链最终都链接到全局上下文。
相关推荐:javascript学习教程
위 내용은 JavaScript 엔진이 JS 코드를 실행하는 방법에 대한 깊은 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!