본문 바로가기

2022-05-18 TIL 항해 10일차(실행 컨텍스트,TDZ,호이스팅,스코프) + 과제

2022. 5. 19.

음... 그래요

일단은 아직은 낯선 내용들이지만 차근차근 공부한 것들을 정리해보았습니다.

#1. 호이스팅, TDZ

Javascript 변수 키워드에는 var, let, const가 있다.

자바스크립트가 처음 등장 된 당시 var 제일 먼저 등장하였고,

var가 가지고 있는 문제가 어이가 없어서, 그 문제점을 보안하기 위해 2015년즈음에 let,const 라는 변수 키워드가 새로 등장하였다.

var는 한번 선언된 변수를 다시 선언할 수 있다.  - 다른 언어에서는 말도 안되는 일이다.

var name = 'bob'
var name = 'john'
console.log(name) // 'john'

 

var는 선언하기 전에 사용할 수 있다. -이게 무슨 일이야

console.log(name) //  undefined
var name = 'john'

이런게 가능한 이유가 바로  호이스팅(hoisting)이 일어나기 떄문이다. (hoist 뜻 : 감아올리다)

JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다.

쉽게 말하면 코드가 실행되기 전에 자바스크립트는 선언에 대한 메모리 부터 할당을 한다.

덕분에 함수를 호추하는 코드를 함수 선언보다 앞서 배치할 수 있었던것.

 

위의 예시의 결과가 undefined가 발생한 이유는

선언은 호이스팅 되지만, 할당은 호이스팅 되지 않기 떄문이다.

다시 한번 요약하자면, 호이스팅이란 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동하는 것을 의미한다.

 

다음은 let, const의 호이스팅이다.

//let
console.log(name)
let name = 'bob' // ReferenceError
 
//const
console.log(name) // ReferenceError
const name='john'

var와는 달리 let과 const는 ReferenceError 를 보여준다.

let 과 const는 호이스팅되지 않는걸가?

아니다 . let과 const도 호이스팅이 된다.

에러가 나온 이유는 TDZ(Temporal Dead Zone) 때문이다

 

 var와는 다르게 위의 사진처럼  const와 let은 TDZ의 영향을 받는다.

할당을 하기 전에는 사용할 수 없게 하는 것이다. 

이는 코드를 예측가능하게 하고, 잠재적인 버그를 줄일 수 있다.

 

예시1)
let age = 30;
function showAge(){
  console.log(age);
}
showAge();

예시1은 문제가 발생하지 않는다.

예시2)
let age = 30;
function showAge(){
  console.log(age);
  let age = 20;
}
showAge();

예시2는 문제가 발생한다.

'let은 호이스팅이 안되는구나' 라고 착각할 수 있지만, 호이스팅은 스코프 단위로 일어나기 떄문이다.

스코프에 대해서는 조금 이따가 나온다.

여기서 스코프는 녹색 선

함수 스코프 내부의 let age = 20; 이 호이스팅을 일으켰다.

만약 호이스팅이 되지 않았다면, 함수 밖에서 선언한 let age = 30 이 정상적으로 찍혀야 했다.

let age = 20; 은 TDZ 아래에 있기 떄문에 오류가 발생하는것.

 

#2. 변수의 생성과정

변수의 생성과정은
1. 선언 단계
2. 초기화 단계
3. 할당 단계
로 이루어진다.

 

var

1.선언 및 초기화 단계 (동시에 이루어짐)
2. 할당 단계

 

let
1. 선언 단계
2. 초기화 단계
3. 할당 단계

 

const
1. 선언 + 초기화 + 할당 단계 (3개가 동시에 이루어짐)

따라서 const만 선언과 동시에 할당까지 안해주면 오류가 발생한다.

아래에 예시를 보자

let name;
name = 'Mike';

var age;
age = 30;

const gender;
gender = 'male' 
//Uncaught SyntaxError: Missing initializer in const declaration

name과 age는 괜찮지만,

const 로 선언한 gender 부분에서 에러가 발생함.

이유는 선언을하면서 바로 할당을 안했기 때문이다.

 

#3. 스코프

위에서 호이스팅은 스코프 단위로 일어난다고 언급하였는데, 스코프는 무엇일까?

먼저 var, 와 let,const 로 나눠질 수 있다.

 

var: 함수 스코프

let,const : 블록 스코프 (함수, if문, for문, while문 등)

여기서 말하는 블록은 중괄호{} 를 의미함.

 

const age = 30;

if(age>19){
	var text = '성인';
}
console.log(txt); //'성인'

var는 if문 내부에서 선언된 var를 외부에서 접근이 가능하다.  이유는 var는 함수 스코프이기 떄문이다

 

const age = 30;

if(age>19){
	let text = '성인';
}
console.log(txt); // Uncaught ReferenceError: txt is not defined

이번에는 let으로 선언해보았는데, 

let은 블록 스코프 이기 때문에 블록 안에서만 let에 접근이 가능하며

이경우에는 오류가 난다.

 

#4 실행 컨텍스트(execution context)

실행 컨텍스트의 개념은 복잡하기에 일단은 부분적으로 공부한다음에 추후 더 공부할 예정이다.

 

실행 컨텍스트

-자바스크립트 엔진 내에서 함수가 실행되는 환경

 

함수라는 것은?

-변수, 매개변수, 내장함수, this 이 4가지로 이루어져 있는 것

 

실행 컨텍스트는 Creation phase(생성 단계)와 Execution phase(실행 단계) 로 나눠져서 만들어진다.

 

실행 컨텍스트 설명에 앞서 용어 설명부터.

Scope chain = execution context cahin

Lexical environment = lexical scope

-Environment record : 변수와 값을 의미

-Outer environment record : 위쪽 변수, 함수를 의미

 

var a = 'Hello';
first();

function frist() {
	var  b = 'Hi';
    second();
    
    function second() {   //second함수가 봤을때 first함수는 위쪽에, 즉 first 함수는 outer 스코프가 된다.
		var c = 'Hey';
 		console.log(a+b+c)
	}
}

실행컨텍스트에는 3종류가 있다.

Global execution context = Global Object (Go)

-this object

-window object

Function execution context = Activation Object(AO)

Eval execution context : 신경쓰지 않아도됨.

 

GO : 빌트인객체 (MATH,STRING 등)과 BOM, DOM , 전역변수

AO : 함수선언, 매개변수, 변수

 

실행 컨텍스트는  두 단계로 나누어짐

1.Creation phase(생성 단계)

GO,AO,this 형성

-Scopechain(outer scope참조: 변수쉐도잉 발생) 뒤에서 설명

-이 떄문에 호이스팅이 가능

-값이 들어가 있지 않는 초기값(var는 선언과 초기화 , let,const는 선언만)

 

 

이렇게 inner scope 에서 outer scope로 가면서 , '이 변수 대체 뭐야?'하는 과정이 scopechain이다.

 

2. Execution phase(실행 단계)

Go,AO,this 값이 할당

-This는 함수호출패턴 또는 lexical scope에 따라 값이 정해짐

 

실습은 https://ui.dev/javascript-visualizer 을 참고하여 진행해보자.


과제: 주석을 풀면 오류가 나는 이유

let b = 1;
function hi () {
    const a = 1;
    let b = 100;
    b++;
    console.log(a,b);
}

//console.log(a);
console.log(b);
hi();
console.log(b);

 

a는 지역변수이기 떄문입니다.

지역 변수(local variable)란 함수 내에서 선언된 변수를 가리킵니다.

이러한 지역 변수는 변수가 선언된 함수 내에서만 유효하며, 함수가 종료되면 메모리에서 사라집니다.

추가로 함수의 매개변수 또한 함수 내에서 정의되는 지역 변수처럼 동작합니다.

 

a와는 반대로, 위 예시에서 b는 전역 변수입니다.

전역 변수(global variable)란 함수의 외부에서 선언된 변수를 가리킵니다.

이러한 전역 변수는 프로그램의 어느 영역에서나 접근할 수 있으며, 웹 페이지가 닫혀야만 메모리에서 사라집니다.

 

아래에는 이와같은 문제를 해결하기 위해, 첫번쨰 줄과 같이 a를 전역 변수로 선언하였습니다.

let a;
let b = 1;
function hi () {
    const a = 1;
    let b = 100;
    b++;
    console.log(a,b);
}

console.log(a); 
console.log(b);
hi();
console.log(b);
댓글