Today I Learned
- javascript 심화 강의 수강 - 실행 컨텍스트, this
javascript 심화 강의
실행 컨텍스트란?
실행 컨텍스트란 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장
생성(활성화) 시점 : 한 ‘실행 컨텍스트’가 콜 스택의 맨 위에 쌓이는 순간 (함수가 실행되는 시점)
생성 시점에 JS 엔진은 해당 컨텍스트에 관련된 코드를 실행 하는데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다.
실행 컨텍스트에 담기는 정보
1. Variable Environment
a. 현재 컨텍스트 내의 식별자 정보
b. 외부 환경 정보
c. 선언 시점 LexicalEnvironment의 snapshot
2. Lexical Environment
a. 선언 시점에는 Variable Environment와 동일하나 변경사항이 실시간으로 반영
3. ThisBinding
a. this 식별자가 바라봐야 할 객체
// ---- 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);
최상단 빈 공간 |
inner context |
outer context |
전역 context |
call stack
context가 하나씩 위로 쌓이는 과정
코드 실행 → 전역(in) → 전역(중단) + outer(in) → outer(중단) + inner(in) →
최상단부터 밑으로 하나씩 stack을 나감
inner(out) + outer(재개) → outer(out) + 전역(재개) → 전역(out) → 코드 종료
콜 스택의 가장 상단에 위치한 부분이 현재 활성화되어 있는 부분, 최상단 아래로는 멈춰 있는 상태
실행 컨텍스트 객체를 모아서 콜 스택에 쌓는다
하나씩 쌓인 context 마다 별개의 실행 컨텍스트 정보를 가진다
VariableEnvironment와 LexicalEnvironment 비교
1. 담기는 내용 : 동일
2. 스냅샷 유지 여부 (snapshot -> 그 순간을 찍어 놓음)
VE : 유지
LE : 유지X (실시간 반영)
3. 실행 컨텍스트를 생성할 때, VE에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LE를 만들고 이후에는 주로 LE를 활용
4. 구성요소: VE와 LE 모두 ‘environmentRecord’와 ‘outerEnvironmentReference’로 구성됨
LexicalEnvironment - environmentRecord와 호이스팅
i. 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)
ii. 수집 대상 정보 : 함수에 지정된 매개변수 식별자, 함수 자체, var로 선언된 변수 식별자
iii. 컨텍스트 내부를 처음부터 끝까지 순서대로 훑어가며 수집 (실행x)
호이스팅
개념: 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것
변수 정보 수집을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행 전의 상태임 (JS 엔진은 코드 실행 전에 이미 모든 변수 정보를 알고 있음)
매개변수 및 변수에 대한 호이스팅
function a (x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
// Hoisting 적용 예시
function a ( ) {
var x; // 매개변수 식별자
var x; // 변수 식별자
var x;
x = 1;
console.log(x); // 1
console.log(x); // 1
x = 2;
console.log(x); // 2
}
참고 https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html
함수 선언문, 함수 표현식의 호이스팅 차이점
함수 정의의 3가지 방식
function a () { /* ... */ } // 함수 선언문. 함수명 a가 곧 변수명
a(); // 실행 ok
var b = function () { /* ... */ } // 익명 함수 표현식. 함수명 b가 곧 변수명
b(); // 실행 ok
var c = function d () { /* ... */ } // 기명 함수 표현식. 변수명은 c, 함수명은 d
c(); // 실행 ok
d(); // 에러!
// 함수 선언문 - 함수 전체가 호이스팅된다
function sum (a, b) {
return a + b;
}
// 함수 표현식 - 변수명 부분만 호이스팅된다 (var multifly)
var multiply = function (a, b) {
return a + b;
}
함수 선언문은 그 자체로 호이스팅 대상이 되지만, 함수 표현식은 변수명 부분만 호이스팅 된다.
함수 선언문을 주의해야 하는 이유
console.log(sum(3, 4)); // 7 -> '3+4=7'
function sum (x, y) {
return x + y;
}
var a = sum(1, 2); // 3 -> '1+2=3'
function sum (x, y) {
return x + ' + ' + y + ' = ' + (x + y);
}
var c = sum(1, 2);
console.log(c);
상단의 sum 함수가 호이스팅되고 난 후에 하단의 sum 함수가 호이스팅되기 때문에, 결과적으로 마지막에 호이스팅된 하단의 sum 함수가 상단의 sum 함수 결과에도 영향을 미친다.
LexicalEnvironment - 스코프, 스코프 체인, outerEnvironmentReference(=outer)
스코프: 식별자에 대한 유효 범위
스코프 체인: 식별자의 유효 범위를 안에서부터 바깥으로 차례로 검색해나가는 것
outerEnvironmentReference: 스코프 체인이 가능토록 하는 것 (외부 환경의 참조 정보)
값이 해당 scope 상에 존재하지 않으면 이것을 호출한 바깥에서 값을 찾음 (안에서 찾지 않음)
스코프 체인의 작동 과정
var v = "전역 변수";
function a() {
//function a Execution Context(EC)
var v = "지역 변수";
function b() {
//function b Execution Context
console.log(v);
}
b();
}
//Global Execution Context
a();
위 코드의 예제를 보면 먼저 글로벌 실행 컨텍스트(GEC)가 실행되고 스택에 쌓인다.
그런 다음 함수 호출 순으로 실행 컨텍스트 스택에 쌓이게 되고, 가장 나중에 호출된 b() 함수가 실행 컨텍스트 안에서부터 탐색을 시작한다.
그러면, b() 함수 안에서 변수 v를 탐색하기 시작하는데, 만약 변수 v가 없으면 b() 함수를 감싸고 있는 외부 함수 a() 함수를 탐색하기 시작한다.
이때 a() 함수 안에 변수 v가 존재하면 안에 있는 v를 참조하게 되고, 만약 없다면 마지막으로 전역 객체를 탐색하여 v를 찾아낸다.
결국 찾지 못한다면, v가 없다고 VM500:1 Uncaught ReferenceError: v is not defined라는 에러를 보게 될 것이다.
반대로 찾았다면, 결괏값은 a() 안에 변수 v가 존재하기 때문에 지역 변수라는 값이 출력이 된다.
하지만 만약, a() 함수 안에 변수 v를 제거한다면 전역 객체에 있는 변수 v의 값 전연 변수가 출력이 될 것이다.
이러한 과정들이 스코프에 담긴 순서대로 탐색하는 즉, 스코프 체인이라고 보면 된다.
결론: 스코프 체인은 자기 자신의 스코프를 제외한 자신과 가장 가까운 변수 객체의 스코프 순으로 접근하는 것
스코프 체인을 쉽게 설명해 놓은 블로그 발견! 강의 내용을 모두 글로 옮기긴 힘들기 때문에 이걸 참고하면 좋을 거 같다.
출처 https://ljtaek2.tistory.com/140
회고
오늘은 하루 종일 자바스크립트 강의만 들었다. 근데 내가 집중을 못하는 건지 진도가 잘 나가지 않는다. 만약에 내일까지 다 못 들어도 주말에 들어야 겠다. 참고로 강의 내용을 TIL에 정리하면서 듣기 때문에 오늘도 TIL 글이 두 개다. 원장님 강의 듣는데 자꾸 고양이가 보이지도 않는 곳에서 우당탕탕 소리를 내서 너무 귀엽고 웃겼다ㅋㅋ
오늘은 새로운 조가 편성된 날이다! 지난 조에 같은 팀이었던 팀원도 한 명 계시고 새로 만난 분들이 대부분이다. 첫날부터 소통이 잘 되고 있는 느낌~ 카메라를 하루종일 켜놔야 된다는 새로운 팀 규칙에 적응하고 있는 중이기도 하다. 근데 카메라를 켜놓으니까 zep이 너무 끊기고 노트북도 뜨거워진 거 같다.😤