Skip to content

Commit 64fc204

Browse files
committed
✏️ 5회차 문서 수정 : strict mode
1 parent b744e80 commit 64fc204

1 file changed

Lines changed: 228 additions & 0 deletions

File tree

Javascript/strict_mode.md

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
ES5 표준까지해도 자바스크립트는 문제가 많았습니다. 그러나 이 시기에도 완성도 높은 프로그래밍을 위해 여러 방법을 강구했죠. 그 중 하나인 엄격(strict) 모드에 대해 알아봅니다.
2+
3+
## strict mode
4+
> 자바스크립트 언어의 문법을 좀 더 엄격히 적용해 문제를 내포하는 코드에 대해 명시적 에러를 발생시킵니다.
5+
6+
다시 한 번 생각해봅시다. 자바스크립트 언어의 문제점은 뭐가 있었을까요? 대표적으로 꼽자면 var 키워드, 변수 호이스팅, 암묵적 전역(Implict global) 등이 있었죠. 암묵적 전역에 대해 코드를 살펴보고 빠르게 넘어가겠습니다.
7+
8+
- 암묵적 전역 : 아무리 봐도 에러인 아래의 코드는 너무나 잘 작동됩니다.
9+
```js
10+
function foo() {
11+
x = 10;
12+
}
13+
foo();
14+
15+
console.log(x); // 10
16+
```
17+
- 코드의 문제를 이해하기 위해 자바스크립트 엔진의 동작 순서를 살펴볼까요
18+
1. foo 함수 내에서 선언하지 않은 x 변수에 값 10을 할당합니다.
19+
2. x 변수가 어디에서 선언되었는지 스코프 체인을 통해 검색합니다.
20+
3. foo 스코프에서 탐색하고, 상위 스코프인 전역 스코프에서 x 변수의 선언을 탐색합니다.
21+
4. 그 어디에도 존재하지 않아 ReferenceError를 발생시켜야하나 엔진은 동적으로 x 프로퍼티를 생성합니다.
22+
5. 전역 객체의 x 프로퍼티는 전역 변수처럼 사용할 수 있게 됩니다. 이러한 현상이 **암묵적 전역**입니다.
23+
24+
이 외에도 많은 문제로 인해 ES5에서 strict mode(엄격 모드)가 추가 되었으며, ESLint 같은 린트 도구로도 이를 강력하게 검사할 수 있습니다.
25+
26+
<br>
27+
28+
## strict mode 적용하기
29+
> 전역의 선두 또는 함수 몸체 선두에 `'use strict';`를 작성합니다.
30+
31+
- 전역의 선두에 작성 시 전역 스코프에 적용됩니다.
32+
```js
33+
'use strict';
34+
35+
function foo(){
36+
x = 10; // ReferenceError: x is not defined
37+
}
38+
foo();
39+
```
40+
41+
- 함수 몸체의 선두에 작성 시 해당 함수 스코프에서만 적용됩니다.
42+
```js
43+
function foo(){
44+
'use strict';
45+
x = 10; // ReferenceError: x is not defined
46+
}
47+
foo();
48+
```
49+
50+
- 선두가 아닌 곳에 작성 시제대로 동작하지 않습니다.
51+
```js
52+
function foo(){
53+
x = 10;
54+
'use strict';
55+
}
56+
foo();
57+
```
58+
59+
<br>
60+
61+
## 주의사항
62+
### 전역에 적용하는 것은 피하기
63+
> 전역에 적용한 strict mode는 스크립트 단위로 적용됩니다.
64+
65+
- 다른 스크립트에 영향을 주지 않고 해당 스크립트에 한정됩니다.
66+
```html
67+
<!DOCTYPE html>
68+
<html lang="en">
69+
70+
<head>
71+
<meta charset="UTF-8">
72+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
73+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
74+
<title>Document</title>
75+
</head>
76+
77+
<body>
78+
<script type="text/javascript">
79+
'user strict';
80+
</script>
81+
<script type="text/javascript">
82+
x = 1;
83+
console.log(x);
84+
</script>
85+
<script type="text/javascript">
86+
'user strict';
87+
88+
y = 1;
89+
console.log(y); // ReferenceError: y is not defined
90+
</script>
91+
</body>
92+
93+
</html>
94+
```
95+
- 스크립트 별로 적용하는 것은 오류를 발생시킬 수 있습니다. 특히 외부 라이브러리를 사용할 때는요.
96+
97+
<br>
98+
99+
### 함수 단위로 적용하는 것은 피하기
100+
> 어떤 함수는 strict mode, 어떤 함수는 non-strict mode? 당연히 바람직하지 않으며, 그런다고 모든 함수에 일일이 strict mode를 적용하는 것도 옳지 않습니다.
101+
102+
- strict mode가 적용된 함수가 참조할 함수 외부의 컨텍스트에 strict mode를 적용하지 않았다면 문제가 발생할 수 있습니다.
103+
```js
104+
(function(){
105+
var x = 10;
106+
107+
function foo(){
108+
'use strict';
109+
110+
x = 20;
111+
}
112+
foo();
113+
}());
114+
```
115+
- `에러가 난다고 적혀있는데 정상적으로 작동하네요?🙄 무슨 일이지...`
116+
117+
그럼 strict mode로 코드를 엄격하게 관리해서 일어나는 일은 뭐가 있을까요?
118+
119+
<br>
120+
121+
## strict mode가 발생시키는 에러
122+
> 암묵적 전역, 변수/함수/매개변수의 삭제, 매개변수 이름 중복, with문 사용 등이 대표적입니다.
123+
124+
### 암묵적 전역
125+
> 선언하지 않은 변수를 참조하면 ReferenceError가 발생합니다.
126+
127+
```js
128+
(function(){
129+
'use strict';
130+
x = 10;
131+
console.log(x); // ReferenceError: x is not defined
132+
}());
133+
```
134+
135+
<br>
136+
137+
### 변수/함수/매개변수의 삭제
138+
> delete 연산자로 해당 프로퍼티를 삭제하면 SyntaxError가 발생합니다.
139+
140+
```js
141+
(function(){
142+
'use strict';
143+
var x = 10;
144+
145+
delete x; // SyntaxError: Delete of an unqualified identifier in strict mode.
146+
147+
function foo(a) {
148+
delete a; // SyntaxError: Delete of an unqualified identifier in strict mode.
149+
}
150+
151+
delete foo; // SyntaxError: Delete of an unqualified identifier in strict mode.
152+
}());
153+
```
154+
155+
<br>
156+
157+
### 매개변수 이름 중복
158+
> 중복된 이름을 사용하면 SytaxError가 발생합니다.
159+
160+
```js
161+
(function(){
162+
'use strict';
163+
164+
function foo(a, a) {
165+
return a + a; // SyntaxError: Duplicate parameter name not allowed in this context
166+
}
167+
168+
console.log(foo(1, 2));
169+
}());
170+
```
171+
172+
<br>
173+
174+
### with문 사용
175+
> 전달된 객체를 스코프 체인에 추가하는 with문을 사용하면 SyntaxError가 발생합니다.
176+
177+
```js
178+
(function(){
179+
'use strict';
180+
181+
with({ x: 1 }){
182+
console.log(x); // SyntaxError: Strict mode code may not include a with statement
183+
}
184+
}());
185+
```
186+
187+
마지막입니다! strict mode를 적용하면 변하는 동작이 존재할까요? 그 답은 `있습니다`이고, 이제 확인해 볼 거에요.
188+
189+
<br>
190+
191+
## strict mode 적용에 의한 변화
192+
> 일반 함수의 this와 arguments 객체의 동작이 변경됩니다.
193+
194+
### 일반 함수의 this
195+
> 일반 함수로 호출하면 this에 undefined가 바인딩됩니다. 생성자 함수가 아닌 일반 함수 내부에서는 this를 사용할 필요가 없기 때문이죠.
196+
197+
```js
198+
(function(){
199+
'use strict';
200+
201+
function foo(){
202+
console.log(this); // undefined
203+
}
204+
foo();
205+
206+
function Foo(){
207+
console.log(this); // Foo
208+
}
209+
new Foo();
210+
}());
211+
```
212+
213+
<br>
214+
215+
### arguments 객체
216+
> 매개변수에 전달된 인수를 재할당하여 변경해도 반영되지 않습니다.
217+
218+
```js
219+
(function(x){
220+
'use strict';
221+
222+
x = 10;
223+
console.log(arguments); // Arguments [callee: (...), Symbol(Symbol.iterator): ƒ]
224+
}());
225+
```
226+
227+
<hr>
228+
<br>

0 commit comments

Comments
 (0)