실행 컨텍스트란 실행할 코드에 제공할 환경정보들을 모아놓은 객체이다. 이것들을 스택의 한 종류인 콜스택에 쌓아올리는데, 이를 통해 가장 위에 쌓인 컨텍스트와 관련된 코드를 먼저 실행하는 환경 및 순서를 보장할 수 있다.
// ---- 1번
var a = 1;
function outer() {
function inner() {
console.log(a); //undefined
var a = 3;
}
inner(); // ---- 2번
console.log(a);
}
outer(); // ---- 3번
console.log(a);
1. 전역컨텍스트 in
2. outer()을 만나 전역 중단 후 outer컨텍스트 in
3. inner()을 만나 outer 중단 후 inner컨텍스트 in
4. inner()실행 후 inner컨텍스트 out
5. outer()재개 후 outer컨텍스트 out
6. 전역 재개 후 전역 out
7. 코드 종료
//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기
function a (x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
매개변수 x에 1이 들어가므로 1, var x;로 초기화했으므로 undefined, x=2로 재할당하였으므로 2가 출력될 것으로 예상된다.
이처럼 매개변수 x를 1을 넣어 실행한 것은 아래와 동일하다.
//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
var x = 1;
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a();
실행결과는 어떨까? 호이스팅이 적용되었을 순서를 생각해보자.
function a () {
var x;
var x;
var x;
x = 1;
console.log(x); //1
console.log(x); //1
x = 2;
console.log(x); //2
}
예상과는 다르게 1,1,2가 출력된다.
//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
console.log(b);
var b = 'bbb';
console.log(b);
function b() { }
console.log(b);
}
a();
이 함수를 예상해보자.
//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
console.log(b); //undefined
var b = 'bbb';
console.log(b); //'bbb'
function b() { }
console.log(b); //f b()
}
a();
function a () {
var b;
function b() {}; // var b = function b() {} 와 동일
console.log(b); // f b()
b='bbb'
console.log(b) // 'bbb'
console.log(b) // 'bbb'
}
a();
예상한 결과와 실제 결과가 다르다. 함수도 hoisting되기 때문이다.
하지만, 함수라고해서 다 hoisting되는 것은 아니다.
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;
}
함수 선언문은 그 자체로 선언을 하는 것이기 때문에 함수 자체가 hoisting되지만, 함수 표현식은 var multiply가 선언, function~~ 부분은 할당 이므로 hoisting되었을 때 사용하지 못한다.
...
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);
선언문은 hoisting되었을 때 사용이 가능하기 때문에 예상치 못한 오류를 발생시킬 수 있다.
따라서 함수는 표현식으로 만들어 사용하는것이 더 안전한 방법이다.
// 아래 코드를 여러분이 직접 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); // 이 값은 뭐가 나올까요? 마찬가지로 이유도!
콜스택 순서에 의해
1. inner함수 실행
2. var a; > console.log(a); > a = 3;
3. 이때 inner 실행컨텍스트가 out되어 outer함수에서 실행되는 console.log(a)는 1번줄의 var a = 1에서의 1이 출력된다.
항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하므로 inner의 a값에 접근하지 못하는 것이다.
'2차 공부 > TIL' 카테고리의 다른 글
24.07.24 콜백지옥 / 동기, 비동기 (0) | 2024.07.24 |
---|---|
24.07.23 This (0) | 2024.07.23 |
24.07.23 변수선언과 데이터 할당 / 불변하다 vs 불변하지 않다. (0) | 2024.07.23 |
24.07.22 JavaScript 문법 종합반 1, 2주차 (0) | 2024.07.22 |
24.07.19 미니프로젝트를 마치며 (0) | 2024.07.19 |