(참고: https://velog.io/@yunn75151/Execution-context)

function three(){
console.log("i love js");
}
function two(){
three();
}
function one(){
two();
}
function zero(){
one();
}
zero(); // i love js

✨zero 실행

✨one 실행

✨two 실행

✨three실행





결국은 특정 실행 컨텍스트가 생성되는(또는 활성화되는) 시점이 콜 스택의 맨 위에 쌓이는(노출되는) 순간을 의미하며. 곧, 현재 실행할 코드에 해당 실행 컨텍스트가 관여하게 되는 시점을 의미한다고 받아들이면 된다!
Call Stack을 더 이해하기 위해 Error를 추가해보자

zero함수안에서 one이 실행되고 나면 error가 발생하도록 했다.

이것이 바로 콜스텍이다. 이런 순서대로 함수가 진행이된다.
에러 전에 있던 콜스택 또한 확인이 가능하다

three 함수 내부에 에러메시지를 넣었을 때, 여기서 에러가 발생되면 그전 콜스택들이 확인 가능해진다.

이런 식으로 에러전에 있던 모든 콜스택을 확인할 수 있다.
(함수3에서 에러발생 > 그것은 two에서 실행 > 그것은 one,zero 에서 실행 > zero는 index.js에 14번째 line에서 실행)

✨ 정리
var a = 3 ( var a를 의미 )이 두가지는 완벽하게 동일하지만, 스냅샷 유지여부는 다름.
function outer() {
let outerVariable = 10;
function inner() {
// inner 함수 내에서 outer 함수의 변수에 접근
console.log(outerVariable);
}
// outer 함수의 내부에서 inner 함수를 호출
inner();
}
// outer 함수 호출
outer();
🎭 호이스팅 적용 전
function a () {
var x = 1;
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
1, undefined, 2로 예상
🎭 호이스팅 적용 후
function a () {
var x;
var x;
var x;
x = 1;
console.log(x);
console.log(x);
x = 2;
console.log(x);
}
a(1);
실제로는, 1, 1, 2 라는 결과가 나옴
function a () {
console.log(b);
var b = 'bbb';
console.log(b);
function b() { }
console.log(b);
}
a();
에러(또는 undefined), ‘bbb’, b함수로 출력예상이지만,
🎭 호이스팅 적용 후
function a () {
var b; // 변수 선언부 호이스팅
function b() { } // 함수 선언은 전체를 호이스팅
console.log(b);
b = 'bbb'; // 변수의 할당부는 원래 자리에
console.log(b);
console.log(b);
}
a();
실제 결과값은 b함수, ‘bbb’, ‘bbb’ 이다
개념 정리
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
그 객체 안에는 3가지가 존재한다.
( VariableEnvironment, LexicalEnvironment, ThisBindings )
- VE와 LE는 실행컨텍스트 생성 시점에 내용이 완전히 같고, 이후 스냅샷 유지 여부가 다르다.
LE는 다음 2가지 정보를 가지고 있다.
✓ record(=environmentRecord) ← 이 record의 수집과정이 hoisting
✓ outer(=outerEnvironmentReference): 함수를 둘러쌓고 있는 외부환경
🎭 호이스팅 적용 전
console.log(sum(1, 2));
console.log(multiply(3, 4));
function sum (a, b) { // 함수 선언문 sum
return a + b;
}
var multiply = function (a, b) { // 함수 표현식 multiply
return a + b;
}
LE는 record와 outer를 수집한다. 그 중, record를 수집하는 과정에서 hoisting이 일어나고, 우리가 익히 알고있는대로 위로 쭉 끌어올려본 결과를 다시 써보면 아래와 같다.
🎭 호이스팅 적용 후
// 함수 선언문은 전체를 hoisting
function sum (a, b) { // 함수 선언문 sum
return a + b;
}
// 변수는 선언부만 hoisting
var multiply;
console.log(sum(1, 2));
console.log(multiply(3, 4));
multiply = function (a, b) { // 변수의 할당부는 원래 자리
return a + b;
};
...
console.log(sum(3, 4));
// 함수 선언문으로 짠 코드
// 100번째 줄 : 시니어 개발자 코드(활용하는 곳 -> 200군데)
// hoisting에 의해 함수 전체가 위로 쭉!
function sum (x, y) {
return x + y;
}
...
...
var a = sum(1, 2);
...
// 함수 선언문으로 짠 코드
// 5000번째 줄 : 신입이 개발자 코드(활용하는 곳 -> 10군데)
// hoisting에 의해 함수 전체가 위로 쭉!
function sum (x, y) {
return x + ' + ' + y + ' = ' + (x + y);
}
...
var c = sum(1, 2);
console.log(c);
...
console.log(sum(3, 4));
// 함수 표현식으로 짠 코드
// 함수 선언부만 위로 쭉!
// 이 이후부터의 코드만 영향을 받아요!
var sum = function (x, y) {
return x + y;
}
...
...
var a = sum(1, 2);
...
// 함수 표현식으로 짠 코드
// 함수 선언부만 위로 쭉!
// 이 이후부터의 코드만 영향을 받아요!
var sum = function (x, y) {
return x + ' + ' + y + ' = ' + (x + y);
}
...
var c = sum(1, 2);
console.log(c);
협업을 많이 하고, 복잡한 코드일 수록. 전역 공간에서 이루어지는 코드 협업일 수록 함수 표현식을 활용하는 습관을 들이도록 하는것이 좋다
A함수 내부에 B함수 선언 → B함수 내부에 C함수 선언(Linked List)한 경우.전역 컨텍스트의 LexicalEnvironment를 참조하게 된다.// 아래 코드를 여러분이 직접 call stack을 그려가며 scope 관점에서 변수에 접근해보세요!
// 어려우신 분들은 강의를 한번 더 돌려보시기를 권장드려요 :)
var a = 1;
var outer = function() {
var inner = function() {
console.log(a); // 이 값은 뭐가 나올지 예상해보세요! 이유는 뭐죠? scope 관점에서!
var a = 3;
};
inner();
console.log(a); // 이 값은 또 뭐가 나올까요? 이유는요? scope 관점에서!
};
outer();
console.log(a); // 이 값은 뭐가 나올까요? 마찬가지로 이유도!
각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다