<aside> 💡 코드를 보다 쉽게 이해, 저장, 수정할 수 있도록 메모리 주소에 이름을 부여하여 의미를 갖도록 만든 형태를 변수/함수라고 함.

</aside>

<aside> 💡 이름 충돌의 문제를 피하기 위해 스코프라는 규칙을 만들어 정의함.

</aside>

클로저에 대해 설명해주세요.

# 등장배경
- 클로저는 자바스크립트 언어 명세에 기재되어 있지 않음. 이 단어는 1964년 Peter J. Landin 의 논문 "The Mechanical Evaluation of Expressions" 에서 등장함.
- 위 정의를 토대로, 현대 프로그래밍 관점에서 해석하자면 이렇게 정의할 수 있음 : **함수 + 함수를 둘러싼 환경 (Lexical environment) = 클로저**
- 클로저는 함수가 생성되는 시점에 생성되며, 생성된 함수의 렉시컬 환경을 포섭한 하나의 개념임. 즉, 개념적인 측면에서 자바스크립트의 모든 함수는 클로저라고 볼 수 있음. 하지만 실제로 모든 자바스크립트 함수를 클로저라고 부르지는 않음!

function a() {
	let a = 'a';

	function b() {
		console.log(a);
	}
}

****# 예시

var color = 'red'; function foo() { var color = 'blue'; // 2 function bar() { console.log(color); // 1 } function setState(new) { color = new; } return setState; } var baz = foo(); // 3 setState('red'); // 4

- `bar`는 자신이 생성된 렉시컬 스코프에서 벗어나 글로벌 환경에서 `baz`라는 이름으로 호출이 됨.
- 실제 동작 결과, `color`를 탐색하는 과정에서 현재 실행 스택과 관련 없는 `foo`에서 값을 찾게 됨. 이는 `baz`를 `bar`로 초기화 하는 과정에서 렉시컬 환경을 `foo`로 결정했기 때문임.
- 일반적으로 `foo` 수행이 끝난 이후 메모리를 회수해야 하지만, `bar`가 여전히 렉시컬 환경인 `foo`를 참조하고 있기 때문에 소멸되지 않고 남아있게 됨.
=> 이처럼 이미 동작이 끝나 소멸되어야 하는 환경을 특정 환경이 참조하고 있는 경우 소멸되지 않고 남아있는 현상을 클로저라고 함. 

스코프에 대해 설명해주세요.

# 스코프란?
- 식별자(변수)의 유효 범위: 어떤 변수가 정의되어 있는 영역을 뜻함. 식별자(변수)가 어디서 어떻게 선언되었는지에 따라 스코프가 결정됨.
- 자바스크립트는 기본적으로 렉시컬 스코프와 함수 레벨 스코프 방식으로 동작함. ES6부터는 블록 레벨 스코프를 지원함.

## 1-1. 전역 스코프 (global scope)
- 코드 내부 어디서든 참조(접근)가 가능한 영역을 뜻함.

## 1-2. 지역 스코프 (local scope)
- 코드 블록({...})이 만든 영역을 뜻함. 자기 자신과 하위 스코프에서만 참조(접근)가 가능함.
- 전역 변수와 지역 변수의 이름이 같을 경우, 전역 변수는 감춰지고 지역 변수를 사용함.

## 2-1. **함수 레벨 스코프 (function-level scope)**
- 함수를 기준으로 스코프를 결정: 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하며 외부에서는 참조(접근)할 수 없음. var 키워드로 선언된 변수가 이 개념에 해당함.
****- 대부분의 프로그래밍 언어는 블록 레벨 스코프를 따르는 반면, 자바스크립트는 함수 레벨 스코프를 따름. 모든 변수가 함수 내부에서 전역적으로 동작하다 보니 전역 변수가 일으키는 예상치 못한 동작, 변수 중복 선언 & 변수 선언 이전 참조 가능으로 인한 문제 발생과 같은 혼란을 야기함.

## 2-2. **블록 레벨 스코프 (block-level scope)**
- 함수 레벨 스코프의 단점을 보완하기 위해 ES6부터 블록 레벨 스코프를 지원하기 시작함.
****- 블록을 기준으로 스코프를 결정: 모든 코드 블록(함수, if, for, try/catch 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 외부에서는 참조(접근)할 수 없음. let/const 키워드로 선언된 변수가 이 개념에 해당함.
- 함수 레벨 스코프의 경우 함수 내부에 선언된 변수는 어디서든 접근이 가능했지만, 블록 레벨 스코프의 경우 변수가 포함된 스코프 내부가 아닌 곳에서 사용할 경우 참조 에러가 발생함.

## 3-1. **렉시컬 스코프 (Lexical scope)**
- 정적/어휘적/수사적 스코프라고도 함. 현대 프로그래밍에서 대부분의 언어들은 이 규칙을 따르고 있음.
- 소스코드가 작성된 문맥에서 결정되는 스코프를 뜻함. 즉, 함수를 어디서 호출했는지가 아닌 어디에 선언하였는지에 따라 정해짐.
****
## 3-2. **동적 스코프 (Dynamic scope)**
- 프로그램의 런타임 도중의 실행 컨텍스트나 호출 컨텍스트에 의해 결정되는 스코프를 뜻함. 즉, 렉시컬 스코프와는 반대로 함수를 어디서 호출했는지에 따라 정해짐.

var , let , const 의 개념 및 차이점을 설명해주세요.

# var
- 동일한 이름으로 여러 번 중복해서 선언이 가능함. 이와 같은 경우, 마지막에 할당된 값이 변수에 저장됨.
- 필요할 때마다 변수를 유연하게 사용할 수 있다는 장점이 될 수도 있지만, 기존에 선언해둔 변수의 존재를 잊고 값을 재할당하는 등의 실수가 발생할 가능성이 큼. 특히 코드량이 많아졌을 때, 같은 이름의 변수명이 여러 번 선언되었다면 어디 부분에서 문제가 발생하는지 파악하기 힘들뿐더러 값이 바뀔 우려가 있음.
- 이를 보완하기 위해 ES6부터 추가된 변수 선언 방식이 `let`과 `const`임.

# let
- `var`와 다르게 `let`은 중복 선언할 경우 해당 변수가 이미 선언되었다는 에러 메시지가 출력됨. (중복 선언 불가능)
- `name = 'a'`와 같이 변수 선언 및 초기화 이후 반복해서 다른 값을 재할당 할 수는 있음.

# const
- `let`과 `const`의 차이점은 `immutable`의 여부임. `const`는 constant(상수)를 뜻하기 때문에 한 번만 선언이 가능하며 값을 바꿀 수도 없음. `let`은 변수에 다른 값을 재할당할 수 있지만, `const`는 재할당 시 에러 메시지가 출력됨.
-  단, 배열과 오브젝트의 값을 변경하는 것은 가능함. 불변을 의미하는 것과 다르게 값을 재할당하는 코드만 불가능하다고 볼 수 있음.

함수 선언문함수 표현식 의 차이점을 설명해주세요.

함수 생성에 필요

# 함수 선언문
`function foo() { ... }`

# 함수 표현식
`const = `
- 함수를 변수에 담은 것

function a () { if (true) { var b = function () { console.log('a') } // const b = function () { console.log('a') } b() } b() }

- 어떤 키워드를 사용하냐에 따라 스코프가 달라짐. `var`를 사용해서 선언하면 함수 레벨 스코프로 동작하고 `let/const`를 사용해서 선언하면 블록 레벨 스코프로 동작함.

<aside> ❓ 생성자도 함께 정리

</aside>