# this

## this arguments

일반적으로 this는 **현재 함수가 실행중인 객체 자신**을 지칭한&#xB2E4;**.** 배운다. 좀 더 의미를 명확하게 하기 위해 <mark style="color:blue;">**주인공**</mark>이라는 표현을 사용하도록 하겠다.

## 객체의 this와 call()

```javascript
const student = {
    no : 1,
    name : "피카츄",
    korean : 50,
    english : 60,
    math : 70
};
```

학생 객체가 있다(시각적 편의를 위해 생성자 함수를 쓰지 않았다).&#x20;

객체에는 **번호(no), 이름(name), 국어점수(korean), 영어점수(english), 수학점수(math)**&#xB97C; 저장할 수 있는 변수가 존재한다. 자바스크립트는 기본적으로 접근 제한이 존재하지 않으므로 각각의 변수에 대한 setter와 getter 메소드를 생성할 필요가 없다.

따라서 합계나 평균을 알고 싶다면 다음과 같은 코드를 작성해야 할 것이다.

```javascript
console.log("총점 : " + (student.korean + student.english + student.math) + "점");
```

backtrick 출력 구문을 사용하면 덧셈 정도는 없앨 수 있다

```javascript
console.log(`총점 : ${student.korean + student.english + student.math}점`);
```

이 경우 객체에 메소드를 추가하면 가독성과 효율성이 좋아진다.

```javascript
const student = {
    no : 1,
    name : "피카츄",
    korean : 50,
    english : 60,
    math : 70,
    //합계를 구하는 함수 추
    total : function(){
        return korean + english + math;
    },
};
```

작성한 뒤 합계를 구하면 오류가 발생한다.

```javascript
console.log(`총점 : ${student.total()}점`);
//ReferenceError : korean is not defined
```

메소드 내부에 korean이 정의되지 않았다는 뜻이며, <mark style="color:red;">**this**</mark> 키워드를 추가하면 주인공의 정보임을 명시하면 오류 없이 출력된다.

<pre class="language-javascript"><code class="lang-javascript">const student = {
    no : 1,
    name : "피카츄",
    korean : 50,
    english : 60,
    math : 70,
    total : function(){
        return this.korean + this.english + this.math;
    },
};

<strong>console.log(`총점 : ${student.total()}점`);//총점 : 180점
</strong></code></pre>

총점을 구하기 위해서 total 함수를 부를 때 다음과 같이 코드를 작성한다.

```javascript
student.total()
```

이 코드는 **`Function.prototype.call`** 함수를 사용하여 다음과 같이 표현할 수 있다.

```javascript
student.total.call(student);
```

{% embed url="<https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-function.prototype.call>" %}
Function.prototype.call() reference
{% endembed %}

따라서 다음과 같은 출력 구문도 정상 작동한다.

```javascript
console.log(`총점 : ${student.total.call(student)}점`);
```

두 방식에 대해 한글로 해석을 달아보면 다음과 같다.

```javascript
//[1] student의 total 함수를 실행한  반환값을 가져와라!
student.total()

//[2] 주인공을 student로 설정하고 student의 total 함수를 실행한 뒤 반환값을 가져와라!
student.total.call(student)
```

결과적으로는 동일한 실행 결과가 나온다. 하지만 \[2] 방식은 주인공을 다르게 설정할 수 있다.

```javascript
const student1 = {
    no : 1,
    name : "파이리",
    korean : 60,
    english : 70,
    math : 80,
    total : function(){
        return this.korean + this.english + this.math;
    },
};
const student2 = {
    no : 2,
    name : "꼬부기",
    korean : 50,
    english : 60,
    math : 70,
    total : function(){
        return this.korean + this.english + this.math;
    },
};

console.log(`총점 : ${student1.total()}점`);//총점 : 210점
console.log(`총점 : ${student2.total.call(student1)}점`);//총점 : 210
```

코드를 단순하게 볼 수 있도록 prototype 등은 생략하였으며 이 코드는 매우 비효율적인 코드이다. 하지만 중요한 점은 함수를 실행할 때 주인공을 변경할 수 있다는 것이다.

## callback 함수의 this

기존 student 객체에 공부를 위한 study 메소드를 추가한다.

```javascript
const student = {
    no : 1,
    name : "이상해씨",
    type : "풀",
    study : function(){
        console.log(this.name + " 학생이 공부를 합니다");
    },
};
```

공부가 끝나면 연속적으로 실행할 작업을 지정하기 위해 매개변수로 함수를 받아서 실행하도록 코드를 추가한다. <mark style="color:blue;">**typeof**</mark>를 이용한 타입 검사를 실시하였다.

```javascript
const student = {
    no : 1,
    name : "이상해씨",
    type : "풀",
    study : function(done){
        console.log(this.name + " 학생이 공부를 합니다");

        if(typeof done === 'function') {
            done();
        }
    },
};
```

위와 같이 구성한 경우 공부만 시키거나 공부 후 해야할 일을 콜백 함수로 알려주면서 실행할 수 있다.

#### 공부만 하도록 시키는 경우

```javascript
student.study();
```

#### 공부 후 해야 할 일을 알려주는 경우

```javascript
student.study(function(){ 
    console.log("공부 끝!"); 
});
```

실행하면 다음과 같이 결과가 나온다.

```javascript
이상해씨 학생이 공부를 합니다
공부 끝!
```

그렇다면 <mark style="color:red;">**this**</mark>에 대해서 알아보고 있는 현 상황에서 study에서의 <mark style="color:red;">**this**</mark>와 콜백 함수에서의 <mark style="color:red;">**this**</mark>는 어떤 대상을 가리킬까?

<div align="left"><figure><img src="/files/lIu1vPFR3q2EFl1NOR4v" alt=""><figcaption></figcaption></figure></div>

출력해보면 study() 에서는 **student** 객체가, callback 함수에서는 **window** 객체가 출력된다. **window**는 웹 브라우저의 root 객체일 뿐 다른 환경이라면 다른 값이 나올 수 있다(ex : process).&#x20;

하지만 공부를 마치고 할 일도 결국 student가 하는 일인데 <mark style="color:red;">**this**</mark>를 **student**로 설정할 수 있다면 좋지 않을까? **no, name, type**과 같은 다른 항목들도 접근할 수 있으니 여러모로 좋을 것이다.

study 메소드의 callback 함수 호출 구문을 변경한다.

```javascript
const student = {
    no : 1,
    name : "이상해씨",
    type : "풀",
    study : function(done){
        console.log(this.name + " 학생이 공부를 합니다");
        
        if(typeof done === 'function') {
            //done();
            done.call(this);
        }
    },
};
```

함수 호출을 **`Function.prototype.call()`**&#xB85C; 해서 study()의 <mark style="color:red;">**this**</mark>(student)가 callback 함수에서도 <mark style="color:red;">**this**</mark>가 될 수 있도록 설정하였다. callback 함수에서 <mark style="color:red;">**this**</mark>를 출력하면 student가 나오는 것을 확인할 수 있다.

<div align="left"><figure><img src="/files/NQHErGyPoRiciNE98pIl" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}

### <mark style="color:red;">Arrow function 이용 시 주의사항</mark>

<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions>

Javascript Arrow function은 this를 가지지 않습니다. 따라서 다음과 같이 코드를 작성할 경우 this는 window로 표시됩니다. <mark style="color:red;">결론적으로 this 사용 시 일반 함수와 화살표 함수는 사용 방법이 달라질 수 있습니다.</mark>

```javascript
student.study(()=>{ 
    console.log("공부 끝!"); 
});
```

{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sysout.co.kr/web/develop-page/js/syntax/this.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
