코어 자바스크립트 3장 ( this )
포스트
취소

코어 자바스크립트 3장 ( this )

해당 포스트는 코어 자바스크립트 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입니다.

일반 함수에서 thisglobalThis입니다.
일반 함수에서 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' ]

📮 레퍼런스

  1. « 코어 자바스크립트 3장 » ( 정재남 지음, 위키북스, 2019 )
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

자바스크립트 완벽 가이드 5장 정리

타입스크립트 유틸리티 기능 만들어보기