Skip to content

Commit 68bb377

Browse files
authored
Merge branch 'ahnlab-220:main' into main
2 parents 0b518d7 + 4ac3e65 commit 68bb377

3 files changed

Lines changed: 317 additions & 0 deletions

File tree

book/공희재/chapter_20.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Chapter 20 - strict mode
2+
3+
## 1. strict mode란?
4+
5+
자바스크립트는 오타나 문법 지식의 미비로 인한 실수를 저지르기 쉬운 언어다. (e.g., implicit global(암묵적 전역) 등)<br/>
6+
개발자의 의도와는 다르게 오류가 발생하는 것을 막기 위해 ES5부터 **strict mode**(엄격 모드)가 추가되었다.
7+
8+
ESLint 같은 린트 도구를 사용해도 strict mode와 유사한 효과를 얻을 수 있다.<br/>
9+
더군다나 린트 도구는 static analysis(정적 분석) 기능으로 소스코드를 실행하기 전에 미리 스캔해 문법적 오류뿐만 아니라<br/>
10+
잠재적 오류까지 찾아내고 리포팅해주는 유용한 도구다.<br/>
11+
(따라서 책에서는 strict mode보다는 **ESLint 같은 린트 도구를 더 선호**한다고 밝히기는 함)
12+
13+
참고로 ES6부터 도입된 **클래스와 모듈은 기본적으로 strict mode**가 적용된다.
14+
15+
## 2. strict mode의 적용
16+
strict mode를 적용하려면 **전역의 선두**, 또는 **함수 몸체의 선두****`'use strict';`** 한 줄만 추가하면 된다.<br/>
17+
전역의 선두에 추가하면 스크립트 전체에 strict mode가 적용되고, 함수 몸체의 선두에 추가하면 해당 함수와 중첩 함수에 strict mode가 적용된다.
18+
```javascript
19+
// 전역 선두에 추가한 예제
20+
'use strict';
21+
22+
function foo() {
23+
x = 10; // ReferenceError: x is not defined
24+
}
25+
foo();
26+
```
27+
28+
```javascript
29+
// 코드의 선두에 추가하지 않으면 제대로 동작하지 않는다
30+
function foo() {
31+
x = 10; // 에러가 발생하지 않음.
32+
'use strict';
33+
}
34+
foo();
35+
```
36+
37+
## 3. 전역에 strict mode를 적용하는 것은 피하자
38+
전역에 적용한 strict mode는 아래 예제처럼 스크립트 단위로 적용된다.
39+
```html
40+
<!DOCTYPE html>
41+
<html>
42+
<body>
43+
<script>
44+
x = 1; // 에러가 발생하지 않음.
45+
console.log(x); // 1
46+
</script>
47+
<script>
48+
'use strict';
49+
y = 1; // ReferenceError: y is not defined
50+
console.log(y);
51+
</script>
52+
</body>
53+
</html>
54+
```
55+
그러나, strict mode 스크립트와 non-strict mode 스크립트를 혼용하는 것은 오류를 발생시킬 수 있다.<br/>
56+
특히 외부 서드파티 라이브러리를 사용하는 경우, 라이브러리가 non-strict mode인 경우도 있기 때문에<br/>
57+
전역에 strict mode를 적용하는 것은 어쨌든 **바람직한 행위가 아니다**.
58+
59+
## 4. 함수 단위로 strict mode를 적용하는 것도 피하자.
60+
함수 안에서 strict mode를 사용하는 것도 권장할만한 행위는 아니다.<br/>
61+
어떤 함수는 strict mode이고 어떤 함수는 non-strict mode인 것 자체가 바람직하지 않으며 모든 함수에 일일이 strict mode를 적용하는 것은 번거로운 일이다.
62+
63+
대신, strict mode는 **즉시 실행 함수로 감싼 스크립트 단위로 적용**하는 것이 바람직하다.
64+
65+
## 5. strict mode가 발생시키는 에러
66+
다음은 strict mode를 적용했을 때, 에러가 발생하는 대표적인 사례다.
67+
68+
### 5-1. 암묵적 전역
69+
애초에 var, let, const 등의 키워드로 **선언하지 않은 변수를 참조하면 `ReferenceError`를 발생**시킨다.
70+
```javascript
71+
(function () {
72+
'use strict';
73+
x = 1;
74+
console.log(x); // ReferenceError: x is not defined
75+
}());
76+
```
77+
78+
### 5-2. 변수, 함수, 매개변수의 삭제
79+
delete 연산자로 변수, 함수, 매개변수를 삭제하면 `SyntaxError`를 발생시킨다.
80+
81+
### 5-3. 매개변수 이름의 중복
82+
**중복하는 매개변수 이름을 사용하면 `SyntaxError`를 발생**시킨다.
83+
```javascript
84+
(function () {
85+
'use strict';
86+
87+
// SyntaxError: Duplicate parameter name not allowed in this context
88+
function foo(x, x) {
89+
return x + x;
90+
}
91+
console.log(foo(1, 2));
92+
}());
93+
```
94+
### 5-4. with 문의 사용
95+
with 문을 사용하면 `SyntaxError`를 발생시킨다. (사실 with 문은 애초에 사용을 지양해야 한다고 책은 언급한다.)
96+
97+
## 6. strict mode 적용에 의한 변화
98+
### 6-1. 일반 함수의 this
99+
strict mode에서 함수를 **일반 함수**로서 호출하면, **`this``undefined`가 바인딩**된다.<br/>
100+
일반 함수 내부에서는 this를 사용할 필요가 없기 때문이다. 단, 이때 에러가 발생하지는 않는다.
101+
```javascript
102+
(function () {
103+
'use strict';
104+
105+
function foo() {
106+
console.log(this); // undefined
107+
}
108+
foo();
109+
110+
function Foo() {
111+
console.log(this); // Foo
112+
}
113+
new Foo();
114+
}());
115+
```
116+
117+
### 6-2. arguments 객체
118+
strict mode에서는 매개변수에 전달된 인수를 재할당해 변경해도, **arguments 객체에 반영되지 않는다**.
119+
```javascript
120+
(function (a) {
121+
'use strict';
122+
123+
// 매개변수에 전달된 인수를 재할당해 변경해도,
124+
a = 2;
125+
126+
// 변경된 인수가 arguments 객체에 반영되지 않는다.
127+
console.log(arguments); // { 0: 1, length: 1 }
128+
}(1));
129+
```
130+
131+
끝.

book/공희재/chapter_21.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Chapter 21 - 빌트인 객체
2+
3+
## 1. 자바스크립트 객체의 분류
4+
자바스크립트 객체는 다음과 같이 크게 3개로 분류할 수 있다.
5+
1. Standard built-in objects 또는 Native objects 또는 Global objects (표준 빌트인 객체)
6+
2. Host objects (호스트 객체)
7+
3. User-defined objects (사용자 정의 객체)
8+
차례대로 살펴 보자.
9+
10+
## 2. Standard built-in objects: 표준 빌트인 객체
11+
자바스크립트는 다음과 같이 40여 개의 표준 빌트인 객체를 제공한다.
12+
* Object
13+
* String
14+
* Number
15+
* Boolean
16+
* Symbol
17+
* Date
18+
* Math
19+
* RegExp
20+
* Array
21+
* Map/Set
22+
* ...
23+
24+
이러한 표준 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체는 다양한 기능의 메서드를 제공한다.
25+
26+
## 3. Wrapper object: 원시값과 래퍼 객체
27+
문자열, 숫자, 불리언 객체를 생성하는 String, Number, Boolean 표준 빌트인 생성자 함수가 존재하긴 하나,<br/>
28+
자바스크립트가 암묵적으로 생성하는 래퍼 객체에 의해 해당 표준 빌트인 객체들의 프로토타입 메서드 또는 프로퍼티를 참조할 수 있게 된다.
29+
30+
따라서 굳이 String, Number, Boolean 표준 빌트인 생성자 함수를 new 연산자와 함께 호출해 문자열, 숫자, 불리언 인스턴스를 생성할 필요가 없으며 권장하지 않는다.
31+
32+
## 4. Global object: 전역 객체
33+
Global object는 코드가 실행되기 전, 자바스크립트 엔진에 의해 그 어떤 객체보다도 먼저 생성되는 특수한, 최상위 객체다.<br/>
34+
브라우저 환경에서는 window가 되고, Node.js 환경에서는 global이 된다.
35+
36+
Global object의 특징은 다음과 같다.
37+
* 개발자가 의도적으로 생성할 수 없음. 즉, Global object를 생성하는 생성자 함수가 제공되지 않는다.
38+
* Global object의 프로퍼티를 참조할 때, 식별자명(e.g., `window`, `global`)을 생략할 수 있다.
39+
40+
### 4-1. Built-in global property: 빌트인 전역 프로퍼티
41+
Built-in global property는 Global object의 프로퍼티를 의미한다. 다음과 같이 주로 애플리케이션 전역에서 사용하는 값을 제공한다.
42+
* `Infinity`
43+
* `NaN`
44+
* `undefined`
45+
46+
### 4-2. Built-in global function: 빌트인 전역 함수
47+
Built-in global function은 애플리케이션 전역에서 호출할 수 있는 빌트인 함수로서, Global object의 메서드다.
48+
* `eval()`
49+
* `isFinite()`
50+
* `isNaN()`
51+
* `parseFloat()`
52+
* `parseInt()`
53+
* `encodeURI() / decodeURI()`
54+
* `encodeURIComponent() / decodeURIComponent()`
55+
56+
### 4-3. Implicit global: 암묵적 전역
57+
선언하지 않은 식별자에 값을 할당하는 코드를 작성하게 되면 마치 참조 에러가 발생할 것 같지만,<br/>
58+
선언하지 않은 그 식별자는 Global object의 프로퍼티가 되기 때문에 마치 전역 변수처럼 동작한다.<br/>
59+
(하지만 전역 '변수'는 아니라 변수 호이스팅이 발생하지 않음을 유의)
60+
61+
이러한 현상을 우리는 Implicit global라 부른다.
62+
63+
끝.

book/공희재/chapter_22.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Chapter 22 - `this`
2+
3+
## 1. `this` 키워드
4+
`this`는, 자신이 속한 객체 혹은 자신이 생성할 인스턴스를 가리키는 self-referencing variable(자기 참조 변수)다.<br/>
5+
`this`는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다.
6+
7+
중요한 점은! `this`가 가리키는 값, 즉 `this` 바인딩은 **함수 호출 방식에 의해 동적으로 결정**된다.<br/>
8+
예제와 함께 살펴 보자.
9+
10+
```javascript
11+
// this는 어디서든지 참조 가능하다.
12+
// 전역에서 this는 전역 객체 window를 가리킨다.
13+
console.log(this); // window
14+
15+
function square(number) {
16+
// 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
17+
console.log(this); // window
18+
return number * number;
19+
}
20+
square(2);
21+
22+
const person = {
23+
name: 'Lee',
24+
getName() {
25+
// 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
26+
console.log(this); // {name: "Lee", getName: ƒ}
27+
return this.name;
28+
}
29+
};
30+
console.log(person.getName()); // Lee
31+
32+
function Person(name) {
33+
this.name = name;
34+
// 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
35+
console.log(this); // Person {name: "Lee"}
36+
}
37+
const me = new Person('Lee');
38+
```
39+
(참고로 strict mode가 적용된 일반 함수 내부의 `this`에서는 undefined가 바인딩된다. 엄밀히 말하면 일반 함수 내부에선 `this`를 사용할 이유가 없기 때문이다.)
40+
41+
함수 호출 방식에 따라 달라지는 `this` 바인딩은 다음 절에서 더 자세히 살펴 보자.
42+
43+
## 2. 함수 호출 방식과 `this` 바인딩
44+
동일한 함수여도 다음과 같이 어떤 방식으로 호출하느냐에 따라 `this`에 바인딩되는 값이 달라진다. 예제와 함께 보자.
45+
1. 일반 함수 호출
46+
2. 메서드 호출
47+
3. 생성자 함수 호출
48+
4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
49+
50+
```javascript
51+
// this 바인딩은 함수 호출 방식에 따라 동적으로 결정된다.
52+
const foo = function () {
53+
console.dir(this);
54+
};
55+
56+
// 동일한 함수도 다양한 방식으로 호출할 수 있다.
57+
58+
// 1. 일반 함수 호출
59+
// foo 함수를 일반적인 방식으로 호출
60+
// foo 함수 내부의 this는 전역 객체 window를 가리킨다.
61+
foo(); // window
62+
63+
// 2. 메서드 호출
64+
// foo 함수를 프로퍼티 값으로 할당하여 호출
65+
// foo 함수 내부의 this는 메서드를 호출한 객체 obj를 가리킨다.
66+
const obj = { foo };
67+
obj.foo(); // obj
68+
69+
// 3. 생성자 함수 호출
70+
// foo 함수를 new 연산자와 함께 생성자 함수로 호출
71+
// foo 함수 내부의 this는 생성자 함수가 생성한 인스턴스를 가리킨다.
72+
new foo(); // foo {}
73+
74+
// 4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
75+
// foo 함수 내부의 this는 인수에 의해 결정된다.
76+
const bar = { name: 'bar' };
77+
foo.call(bar); // bar
78+
foo.apply(bar); // bar
79+
foo.bind(bar)(); // bar
80+
```
81+
82+
### 2-1. 일반 함수 호출
83+
함수를 일반 함수로 호출하면, 함수 내부의 `this`에는 Global object가 바인딩된다. (e.g., `window`)<br/>
84+
그 어떤 함수라도(**중첩 함수, 콜백 함수 포함**), 일반 함수로 호출된다면 `this`에는 Global object가 바인딩된다.<br/>
85+
(단, strict mode가 적용된 일반 함수 내부의 `this`에는 `undefined`가 바인딩된다.)
86+
87+
이런 자바스크립트의 특징은 보통의 경우 문제가 되기 때문에,<br/>
88+
중첩 함수나 콜백 함수 내부의 `this` 바인딩을 메서드의 `this`와 일치시키기 위한 여러 방법이 존재한다.
89+
* Function.prototype.apply/call/bind 메서드를 활용해 명시적으로 `this`를 바인딩하거나,
90+
* 화살표 함수를 이용해 `this` 바인딩을 일치시킬 수도 있다.
91+
92+
### 2-2. 메서드 호출
93+
메서드 내부의 `this`에는 그 메서드를 호출한 객체가 바인딩된다.<br/>
94+
메서드 내부의 `this`는 그 메서드 객체를 가리킬 것처럼 보일 수도 있겠지만 아니다. (메서드란 것은 프로퍼티에 바인딩된, 엄연히 독립적인 함수이자 객체이기 때문에 그렇게 오해할만함)<br/>
95+
메서드 내부의 `this`는 메서드를 가리키는 객체와는 관계가 없고, **그 메서드를 호출한 객체에 바인딩된다는 사실을 유념하자.**
96+
97+
### 2-3. 생성자 함수 호출
98+
생성자 함수 내부의 `this`에는 생성자 함수가 (미래에) 생성**** 인스턴스가 바인딩된다.
99+
100+
### 2-4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
101+
(apply, call 메서드 내용은 생략)<br/>
102+
**bind 메서드**는 메서드의 `this`와 메서드 내부의 중첩 함수 또는 콜백 함수의 `this`가 불일치하는 문제를 해결하기 위해 유용하게 사용된다.<br/>
103+
예제와 함께 살펴 보자.
104+
105+
```javascript
106+
const person = {
107+
name: 'Lee',
108+
foo(callback) {
109+
// bind 메서드로 callback 함수 내부의 this 바인딩을 전달
110+
setTimeout(callback.bind(this), 100);
111+
}
112+
};
113+
114+
person.foo(function () {
115+
console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
116+
});
117+
```
118+
119+
120+
**⭐최종 정리⭐** <br/>
121+
<img src="https://github.com/user-attachments/assets/54e5612d-ca38-4045-95b8-d3a9631e0a55" width="60%" />
122+
123+
끝.

0 commit comments

Comments
 (0)