해당 포스트는 코어 자바스크립트 3장을 정리한 포스트입니다.
주관적으로 해석한 내용이 들어가 있어서 잘못된 내용이 포함될 수 있습니다.
또한 교재의 모든 내용을 정리하지 않고 주관적인 판단에 의해 필요한 내용만 작성했습니다.
📌 this 결정 시점
this
는 함수의 실행 시점에 값이 바인딩 됩니다.
this
는 실행 컨텍스트가 콜 스택에 등록되는 시점에 결정됩니다.
그리고 실행 컨텍스트는 거의 함수가 호출될 때 생성됩니다.
즉, 함수의 선언 시점이 아니고 함수의 실행 시점에 결정된다는 것입니다.
📌 함수의 this vs 메서드의 this
일반적으로 메서드는 객체의 프로퍼티에 할당된 함수라고 생각합니다.
이 말보다는 객체의 프로퍼티로써 호출되는 함수를 메서드라고 하는 것이 더 맞는 것 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
const func = function () {
console.log(this);
};
const obj = {
func,
};
// 함수로써 호출 ( this === globalThis )
func();
// 메서드로써 호출 ( this === obj )
obj.func();
화살표 함수인 경우와 call()
, apply()
, bind()
는 일단 제외한 일반적인 경우의 this
입니다.
일반 함수에서 this
는 globalThis
입니다.
일반 함수에서 this
는 본인을 호출한 주체 ( .
혹은 []
앞에 있는 객체 )
📌 화살표 함수의 this
화살표 함수는 실행 컨텍스트를 생성하는 시점 this
바인딩을 하지 않고 상위 스코프가 참조하는 this
를 갖습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const obj = {
func() {
console.log(this); // (1)
const inner = () => {
console.log(this); // (2)
};
inner();
},
};
// (1) obj ( 호출 주체 )
// (2) obj ( 상위 스코프의 this )
obj.func();
const func = obj.func;
// (1) globalThis ( 함수로써 호출 )
// (2) globalThis ( 상위 스코프의 this )
func();
obj.func();
로 호출했을 때의 this
가 조금 더 사고의 흐름에 맞는 값이 나오죠.
📌 콜백 함수의 this
일반적으로 콜백 함수의 this
는 콜백 함수를 만든 제작자 외에 아무도 알 수 없습니다.
물론 직접 호출해보면 알 수 있긴 하죠. 그리고 addEventListener()
같은 유명한 함수는 이미 알고 있죠.
저희가 위에서 일반 함수의 this
는 호출 시점에 결정된다고 이해했습니다.
따라서 콜백 함수는 저희가 만든 함수에서 콜백을 호출하는 것이 아니라면 호출 시점을 볼 수 없어서 this
값을 예측할 수 없습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button type="button">click me</button>
<script>
const $button = document.querySelector("button[type='button']");
$button.addEventListener("click", function (e) {
console.log(this); // $button
});
// 제가 알기로는 화살표 함수는 this 바인딩의 변경이 불가능해서 "globalThis"가 나오는 것 같습니다. ( 확실하지 않음 )
$button.addEventListener("click", (e) => {
console.log(this); // globalThis
});
</script>
</body>
</html>
📌 생성자 함수의 this
생성자 함수에서의 this
는 생성될 객체를 가리킵니다.
1
2
3
4
5
6
7
8
const Person = function (name, age) {
this.name = name;
this.age = age;
};
const person = new Person("alice", 26);
console.log(person); // Person { name: 'alice', age: 26 }
물론 위와 같은 코드가 문제는 없지만 안쓰는게 좋은 것 같습니다.
객체를 만들기 위해서는 class
라는 문법이 있기 때문에 함수는 함수로써의 역할만 하는게 좋을 것 같다는 개인적인 생각입니다.
위와 같은 구문은 생성자 함수/일반 함수의 모호함을 갖기 때문에 화살표 함수를 사용하는 것이 제일 좋은 것 같습니다.
화살표 함수는 생성자 함수로 사용할 수 없어서 애초에 다른 경우의 수를 생각하지 않아도 돼죠.
📌 함수의 this를 바꾸는 방법
함수의 this
를 바꾸는 메서드들의 사용법과 활용 예시입니다.
0️⃣ call() ( Function.prototype.call(thisArg[, arg1[, arg2[, …]]]) )
1
2
3
4
5
6
const func = function (x, y, z) {
console.log(this, x, y, z);
};
// { name: "alice" } 1 2 3
func.call({ name: "alice" }, 1, 2, 3);
1️⃣ apply() ( Function.prototype.apply(thisArg[, argsArray]) )
1
2
3
4
5
const func = function (x, y, z) {
console.log(this, x, y, z);
};
func.apply({ name: "alice" }, [1, 2, 3]);
2️⃣ bind() ( Function.prototype.apply(thisArg[, arg1[, arg2[, …]]]) )
1
2
3
4
5
6
7
const func = function (x, y) {
console.log(this, x, y);
};
const bindedFunc = func.bind({ v: 10 }, 1, 2);
bindedFunc();
3️⃣ 활용법
- 객체에서 배열 메서드 사용하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 유사 배열 객체 ( key에 0이상의 양수가 있고, length가 0이상의 양수 )
const obj = {
0: "apple",
1: "blue",
2: "color",
length: 3,
};
Array.prototype.push.call(obj, "delete");
console.log(obj); // { '0': 'apple', '1': 'blue', '2': 'color', '3': 'delete', length: 4 }
// ES6 이전
const arr = Array.prototype.slice.call(obj);
console.log(arr); // [ 'apple', 'blue', 'color', 'delete' ]
// ES6 이후
const arr2 = Array.from(obj);
console.log(arr2); // [ 'apple', 'blue', 'color', 'delete' ]
📮 레퍼런스
- « 코어 자바스크립트 3장 » ( 정재남 지음, 위키북스, 2019 )