Skip to content

Commit ff32174

Browse files
committed
chapter 15 업로드
1 parent aa90416 commit ff32174

1 file changed

Lines changed: 301 additions & 0 deletions

File tree

book/이용우/chapter_15.md

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
# Chapter 15 - let, const 키워드와 블록 레벨 스코프
2+
3+
ES5까지 변수를 선언할 수 있는 유일한 방법은 `var` 키워드를 사용하는 것입니다.
4+
`var` 키워드는 다음과 같은 특징을 가지고 있습니다.
5+
6+
<br><br>
7+
8+
#### var - 변수 중복 선언 허용
9+
`var` 키워드로 선언한 변수는 중복 선언이 가능합니다.
10+
11+
``` js
12+
var x = 1;
13+
var y = 1;
14+
15+
// var 키워드를 사용하면 같은 스코프 내에서 중복 선언을 허용한다.
16+
var x = 100;
17+
18+
// 초기화 문이 없는 변수 선언문은 무시된다.
19+
var y;
20+
21+
console.log(x); // 100
22+
console.log(y); // 1
23+
```
24+
25+
만약 동일한 이름의 변수가 이미 선언되어 있는 것을 모르고 변수를 중복 선언하며 값을 할당했을 경우, 의도치 않게 먼저 선언된 변수 값이 변경되는 부작용이 발생합니다.
26+
27+
28+
<br><br>
29+
30+
#### var - 함수 레벨 스코프
31+
`var` 키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하게 됩니다.
32+
따라서 함수 외부에서 `var` 키워드로 선언한 변수는 블록 내에서 선언해도 모두 전역 변수가 됩니다.
33+
34+
``` js
35+
var x = 1;
36+
37+
if (true) {
38+
// x는 전역 변수이다. 이미 선언된 전역 변수 x가 있으므로 x는 중복 선언된다.
39+
// 의도치 않게 변수값이 변경되는 부작용이 발생한다.
40+
var x = 100;
41+
}
42+
43+
console.log(x); // 100
44+
```
45+
46+
`for` 문의 변수 선언문에서 `var` 키워드로 선언한 변수도 전역 변수가 됩니다.
47+
48+
<br>
49+
50+
``` js
51+
var i = 10;
52+
53+
// for 문의 변수 선언문에서 var 키워드로 선언한 변수도 전역 변수가 된다.
54+
for (var i = 0; i < 5; i++) {
55+
console.log(i); // 0 1 2 3 4
56+
}
57+
58+
// 의도치 않게 i 변수의 값이 변경된다.
59+
console.log(i); // 5
60+
```
61+
62+
<font color='orange'>함수 레벨 스코프는 전역 변수를 남발할 가능성을 높입니다.
63+
이로 인해 의도치 않게 전역 변수를 중복 선언하는 경우가 발생합니다.</font>
64+
65+
66+
<br><br>
67+
68+
#### var - 변수 호이스팅
69+
`var` 키워드로 변수를 선언하면 변수 호이스팅에 의해 변수 선언문이 스코프의 선두로 끌어올려진 것처럼 동작합니다.
70+
> `var` 키워드로 선언한 변수는 변수 선언문 이전에 참조할 수 있다.
71+
72+
``` js
73+
console.log(foo); // undefined
74+
75+
// 변수에 값을 할당
76+
foo = 123;
77+
console.log(foo); // 123
78+
79+
// 변수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 실행된다.
80+
var foo;
81+
```
82+
83+
84+
<br><br><hr>
85+
86+
### let 키워드
87+
`var` 변수의 단점을 보완하기 위해 ES6에서는 새로운 변수 키워드인 `let``const`를 도입했습니다.
88+
89+
<br>
90+
91+
#### let - 변수 중복 선언 금지
92+
`var` 키워드로 이름이 동일한 변수를 중복 선언하면 아무런 에러가 발생하지 않습니다.
93+
하지만 `let` 키워드로 이름이 같은 변수를 중복 선언하면 문법 에러(`SyntaxError`)가 발생합니다.
94+
95+
``` js
96+
// var 키워드는 중복 선언을 허용함
97+
var foo = 123;
98+
var foo = 456;
99+
100+
// let 키워드는 중복 선언을 허용하지 않음
101+
let bar = 1234;
102+
let bar = 5678; // Uncaught SyntaxError: Identifier 'bar' has already been declared
103+
```
104+
105+
<br>
106+
107+
#### let - 블록 레벨 스코프
108+
`var` 키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하는 함수 레벨 스코프를 따르지만,
109+
`let` 키워드로 선언한 변수는 모든 코드 블록(함수, if, for, while, try/catch 등)을 지역 스코프로 인정하는 블록 레벨 스코프를 따릅니다.
110+
111+
``` js
112+
let foo = 1; // 전역 변수
113+
{
114+
let foo = 2; // 지역 변수
115+
let bar = 3; // 지역 변수
116+
}
117+
118+
console.log(foo); // 1
119+
console.log(bar); // ReferenceError: bar is not defined
120+
```
121+
122+
<br>
123+
124+
#### let - 변수 호이스팅
125+
`var` 키워드로 선언한 변수와 달리 `let` 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작합니다.
126+
127+
``` js
128+
console.log(foo); // Uncaught ReferenceError: foo is not defined
129+
let foo;
130+
```
131+
132+
`let` 키워드로 선언한 변수는 "선언 단계"와 "초기화 단계"가 분리되어 진행됩니다.
133+
> 즉, 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행된다.
134+
135+
`let` 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 시작 지점(변수 선언문)까지 변수를 참조할 수 없습니다.
136+
이처럼 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대(Temporal Dead Zone; TDZ)라고 부릅니다.
137+
138+
<img width="350" alt="image" src="https://github.com/user-attachments/assets/135c7a43-7a61-4518-9461-0251b894e1a5">
139+
140+
<br>
141+
142+
ES6에서 도입된 `let`, `const`, `class`를 사용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다는 것을 기억합시다.
143+
144+
145+
<br><br>
146+
147+
#### 전역 객체와 let
148+
`var` 키워드로 선언한 전역 변수와 전역 함수, 그리고 선언하지 않은 변수에 대한 값을 할당한 암묵적 전역은 전역 객체 `window`의 프로퍼티가 됩니다.
149+
150+
그리고 전역 객체의 프로퍼티를 참조할 때 `window`를 생략할 수 있습니다.
151+
152+
``` js
153+
// 전역 변수
154+
var x = 1;
155+
156+
// 암묵적 전역
157+
y = 2;
158+
159+
// 전역 함수
160+
function foo() {}
161+
162+
// var 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티이다.
163+
console.log(window.x); // 1
164+
console.log(x); // 1
165+
166+
// 암묵적 전역은 전역 객체 window의 프로퍼티이다.
167+
console.log(window.y); // 2
168+
console.log(y); // 2
169+
170+
// 함수 선언문으로 정의한 전역 함수는 전역 객체 window의 프로퍼티이다.
171+
console.log(window.foo); // foo() {}
172+
console.log(foo); // foo() {}
173+
```
174+
175+
<br>
176+
177+
단, `let`, `const` 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다.
178+
> `window.foo`와 같이 접근할 수 없다.
179+
180+
`let` 전역 변수는 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드) 내에 존재하기 때문입니다.
181+
182+
``` js
183+
let x = 1;
184+
185+
// let, const 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티가 아니다.
186+
console.log(window.x); // undefined
187+
console.log(x); // 1
188+
```
189+
190+
191+
<br><br><hr>
192+
193+
### const 키워드
194+
`const` 키워드는 상수(constant)를 선언하기 위해 사용합니다.
195+
하지만 반드시 상수만을 위해 사용하지는 않는다.
196+
197+
`const` 키워드의 특징은 `let` 키워드와 대부분 동일하므로
198+
`let` 키워드와 다른 점을 중점으로 살펴보도록 합시다.
199+
200+
<br>
201+
202+
#### 선언과 초기화
203+
<font color='orange'>const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 합니다. </font>
204+
205+
``` js
206+
const foo = 1;
207+
```
208+
그렇지 않으면 문법 오류(SyntazError)가 발생한다.
209+
210+
`const` 키워드로 선언한 변수는 `let` 키워드로 선언한 변수와 마찬가지로 블록 레벨 스코프를 가지며, 변수 호이스팅이 발생하지 않는 것 처럼 동작합니다.
211+
212+
213+
``` js
214+
{
215+
// 변수 호이스팅이 발생하지 않는 것 처럼 동작한다.
216+
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
217+
const foo = 1;
218+
console.log(foo); // 1
219+
}
220+
221+
// 블록 레벨 스코프를 가진다.
222+
console.log(foo); // ReferenceError: foo is not defined
223+
```
224+
225+
<br>
226+
227+
#### 재할당 금지
228+
`var` 또는 `let` 키워드로 선언한 변수는 재할당이 자유로우나
229+
<font color='orange'>const 키워드로 선언한 변수는 재할당이 금지됩니다. </font>
230+
231+
``` js
232+
const foo = 1;
233+
foo = 2; // TypeError: Assignment to constant variable
234+
```
235+
236+
237+
<br>
238+
239+
#### 상수
240+
`const` 키워드로 선언한 변수에 원시 값을 할당한 경우 변수 값을 변경할 수 없습니다.
241+
**상수는 재할당이 금지된 변수를 의미합니다.**
242+
243+
<font color='orange'>상수는 상태 유지와 가독성, 유지보수의 편의를 위해 적극적으로 사용되어야 합니다. </font>
244+
245+
``` js
246+
// 세전 가격
247+
let preTaxPrice = 100;
248+
249+
// 세후 가격
250+
// 0.1의 의미를 모르기 때문에 가독성에 좋지 않다
251+
let afterTaxPrice = preTaxPrice + (preTaxPrice + 0.1)
252+
console.log(afterTaxPrice); // 110
253+
```
254+
255+
여기서 0.1은 세율을 의미하는 값으로 쉽게 바뀌지 않는 값이며, 프로그램 전체에서 고정적으로 사용되는 값입니다. 이런 경우에 상수로 정의 시, 값의 의미를 쉽게 파악살 수 있고 변경될 수 없는 고정값으로 사용할 수 있습니다.
256+
257+
<br>
258+
259+
일반적으로 상수의 이름은 대문자로 선언해 상수임을 명확히 나타냅니다.
260+
여러 단어로 이뤄진 경우에는 언더스코어(_)로 구분해서 스네이크 케이스로 표현하는 것이 일반적입니다.
261+
262+
``` js
263+
const TAX_RATE = 0.1;
264+
265+
let preTaxPrice = 100;
266+
let afterTaxPrice = preTaxPrice + (preTaxPrice + TAX_RATE);
267+
268+
console.log(afterTaxPrice); // 110
269+
```
270+
271+
272+
<br><br>
273+
274+
275+
#### const 키워드와 객체
276+
`const` 키워드로 선언된 변수에 원시 값을 할당한 경우 값을 변경할 수 없습니다.
277+
하지만 <font color='orange'>const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 있습니다.</font>
278+
279+
``` js
280+
const person = {
281+
name: 'Lee'
282+
};
283+
284+
// 객체는 변경 가능한 값입니다. 따라서 재할당 없이 변경이 가능합니다.
285+
person.name = 'Kim';
286+
console.log(person); // {name: "Kim"}
287+
```
288+
289+
**`const` 키워드는 재할당을 금지할 뿐 "불변"을 의미하지 않는다는 것을 기억합시다.**
290+
291+
292+
<br><br><hr>
293+
294+
### var, let, const
295+
`var``let`, `const` 키워드는 다음 상황에서 사용하는 것을 권장합니다.
296+
297+
- ES6을 사용한다면 `var` 키워드는 사용하지 않는다.
298+
- 재할당이 필요한 경우에 한정해 `let` 키워드를 사용합니다. 이때 변수의 스코프는 최대한 좁게 만든다.
299+
- 변경이 발생하지 않고 읽기 전용으로 사용되는 원시 값과 객체에는 `const` 키워드를 사용하는 것을 추천한다.
300+
301+

0 commit comments

Comments
 (0)