# [3장] this - 북 스터디

<div class="bg-yellow-50 text-3xl text-center font-bold my-4">🤓 스터디원 🤓</div>

<div class="w-full flex flex-col md:flex-row items-center justify-center gap-8 text-sm border dark:border-slate-700 rounded-xl p-4">

<div class="w-24 md:ml-4  p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/eeeyooon.png" />
  <span class="font-semibold">강지윤</span>
  <a href="https://github.com/eeeyooon">@eeeyooon</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/lulla-by.png" />
  <span class="font-semibold">이예솔</span>
  <a href="https://github.com/lulla-by">@lulla-by</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/sryung1225.png" />
  <span class="font-semibold">이성령</span>
  <a href="https://github.com/sryung1225">@sryung1225</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/Stilllee.png" />
  <span class="font-semibold">이에스더</span>
  <a href="https://github.com/Stilllee">@Stilllee</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/chaehaeun.png" />
  <span class="font-semibold">채하은</span>
  <a href="https://github.com/chaehaeun">@chaehaeun</a>
</div>

</div>

<br>
<br>

# [코딩 마을 방범대 : 3장. this](https://github.com/Coding-Village-Protector/core-js/blob/3.this/%5B3%EC%9E%A5%5D%20this/%EC%9D%B4%EC%98%88%EC%86%94.md)

## 질문과 답변

### 1\. [함수 내부의 this 바인딩을 변경하는 방법](https://github.com/Coding-Village-Protector/core-js/issues/12)

#### 함수 내부의 this 바인딩을 변경하는 방법
```js
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!

    function c() {
      console.log(this.a); // global!
    }
    c();
  }
}
obj.b();
```
위 코드에서 메서드 `b`의 `this`는 `obj`객체를 가리킵니다. 그러나 `b`메서드 내부에 정의된 `c`함수는 일반 함수로 호출되므로, `this`가 전역 객체를 가리키게 됩니다.

만약, `c`의 `this`가 전역객체가 아닌 `obj`를 바라보게 하려면 어떻게 해야할까요?

여러 방법 중 한 가지를 선택하고 예시코드와 함께 설명해주세요.

<details data-node-type="hn-details-summary">
<summary>chaehaeun</summary>
<div>
`c`를 화살표 함수로 정의하게 되면 `c` 함수 내부의 `this`가 `obj` 객체를 가리키게 됩니다.

<pre><code>
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a);

    const c = () => {
      console.log(this.a);
    }
    c();
  }
}
obj.b();
</pre></code>

화살표 함수는 자신만의 `this`를 가지지 않기 때문에 자신이 선언된 렉시컬 스코프의 `this` 값을 상속 받습니다. 따라서 화살표 함수로 선언된 `c`는 `b`의 `this`를 상속 받아 `obj`를 가리키게 됩니다.
</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>eeeyooon</summary>
<div>
제가 선택한 방법은 bind 메서드를 사용하는 것입니다. bind는 새로운 함수를 생성하며, 이 함수의 this를 메서드에서 전달된 첫 번째 인수로 설정합니다. 따라서 bind를 사용하면 내부 함수 c의 this 값을 b의 this과 동일하게 obj를 바라보게 할 수 있습니다.

<pre><code>
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!

    var c = function() {
      console.log(this.a); // object!
    }.bind(this);

    c();
  }
}
obj.b();
</pre></code>

</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>lulla-by</summary>
<div>
위에 답변해주신 분들께서 화살표 함수와 `bind` 메서드를 활용하는 방법을 설명해주셔서 저는 변수를 활용하여 우회하는 케이스로 접근해봤습니다.
<br>
<br>
해당 방식은 es5까지 자체적으로 내부 함수에 `this`를 상속할 방법이 없을 때 사용한 방식으로 살짝 허무하지만 기대한대로 작동합니다.
<pre><code>
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!

    var self = this;

    function c() {
      console.log(self.a); // object!
    }
    c();
  }
}
obj.b();
</code></pre>
</div data-type="detailsContent">
</details>

**출제자 : Stilllee**
> **1. 변수명을 이용한 우회** <br>
`this`를 다른 변수에 할당하고 내부 함수에서 이 변수를 사용하는 방식으로, `this`의 값이 함수가 선언될 때 결정되는 것을 활용합니다.
일반적으로는 `self`, `that`, `_this`, `_` 등의 변수명을 사용합니다.
```js
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    var self = this;
    console.log(this.a); // object!
>
    function c() {
      console.log(self.a); // object!
    }
    c();
  }
}
obj.b();
```
<br>
>
**2. 화살표 함수** <br>
ES6에서 도입된 화살표 함수는 자체적인 `this`바인딩을 갖지 않고, 상위 스코프의 `this`를 그대로 사용합니다. 
```js
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!
>
    const c = () => {
      console.log(this.a); // object!
    }
    c();
  }
}
obj.b();
```
<br>
>
**3. `call` / `apply` 메서드** <br>
`call` 또는 `apply` 메서드를 사용하여 함수를 호출하면서 `this` 값을 명시적으로 바인딩 할 수 있습니다. 
```js
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!
>
    function c() {
      console.log(this.a); // object!
    }
    c.call(this);
  }
}
obj.b();
```
<br>
>
**4. `bind` 메서드** <br>
`bind`메서드를 사용하여 함수의 `this`를 고정시킬 수 있습니다. 이렇게 하면 함수가 어디에서 호출되더라도 `this`는 `bind`에 전달된 객체를 가리킵니다.
```js
var a = "global!";
var obj = {
  a: "object!",
  b: function() {
    console.log(this.a); // object!
>
    function c() {
      console.log(this.a); // object!
    }.bind(this);
    c();
  }
}
obj.b();
```

<br>

---

<br>

### 2\. [메서드의 this와 메서드 내부의 콜백 함수의 this](https://github.com/Coding-Village-Protector/core-js/issues/13)

#### 메서드의 this와 메서드 내부 콜백 함수의 this 불일치 문제를 해결 후 설명해주세요.
```js
const myObj = {
  myProperty: 'Hello, world!',
  outerFunc: function() {
    console.log(this.myProperty); // 'Hello, world!'
    setTimeout(function innerFunc() {
      console.log(this.myProperty); // undefined
    }, 1000);
  }
};

myObj.outerFunc();
```
현재 `innerFunc` 함수 내부에서의 `this.myProperty`는 `undefined`를 출력합니다. 
이는 `innerFunc`가 `myObj` 객체의 컨텍스트를 `this`로 가지지 않기 때문입니다.

`innerFunc` 내에서 `this.myProperty`가 `myObj.myProperty`를 정확히 참조하도록 하려면 코드를 어떻게 수정해야 할까요? 

코드를 수정한 후 **(1)`innerFunc`가 왜 `undefined`를 출력했는지**와 **(2)이 문제를 해결한 방법**, 두 가지에 대해 설명해주세요.

<details data-node-type="hn-details-summary">
<summary>eeeyooon</summary>
<div>
<pre><code>
const myObj = {
  myProperty: 'Hello, world!',
  outerFunc: function() {
    console.log(this.myProperty); // 'Hello, world!'
    setTimeout(() => { //
      console.log(this.myProperty); // 'Hello, world!'
    }, 1000);
  }
};

myObj.outerFunc();
</pre></code>

(1) 기존 코드 innerFunc에서 this.myProperty가 `undefined`를 출력한 이유는 `setTimeout`에 의해 호출된 일반 함수 내에서의 `this`는 전역 객체를 가리키기 때문입니다. 이때 myProperty는 전역 객체가 아니기 때문에 undefined가 됩니다.
<br>
<br>

(2) setTimeout의 콜백 함수를 일반 함수(innerFunc)에서 화살표 함수로 변경하여 해결했습니다. 이 화살표 함수는 outFunc의 this를 상속받으므로, this.myProperty는 myObj의 myProperty를 참조하게 됩니다.
</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>Stilllee</summary>
<div>
**(1) : `innerFunc`에서 `undefined` 출력의 이유**<br>
<li>문제 코드에서 `innerFunc`는 `setTimeout`내의 콜백 함수로 사용되었습니다. </li>
<li>자바스크립트에서 `setTimeout`과 같은 내장 함수 내에서 일반 함수로 호출되는 콜백함수의 `this`는 기본적으로 전역 컨텍스트를 가리킵니다.</li>
<li>따라서, 전역 스코프에는 `myProperty`라는 이름의 속성이 존재하지 않기 때문에 `undefined`를 반환하는 것입니다.</li>
<br>
<br>

**(2) : `bind`메서드로 문제 해결**
<pre><code>
const myObj = {
  myProperty: "Hello, world!",
  outerFunc: function () {
    console.log(this.myProperty);
    setTimeout(
      function innerFunc() {
        console.log(this.myProperty);
      }.bind(this),
      1000
    );
  },
};

myObj.outerFunc();
</code></pre>

<li>`bind`메서드를 사용하여 `innerFunc`의 `this`를 `outerFunc`의 `this`인 `myObj`객체로 명시적으로 설정했습니다.</li>
<li>`.bind(this)`를 호출함으로써 `innerFunc`내의 `this`는 항상 `outerFunc`가 호출될 때의 컨텍스트인 `myObj`객체를 가리키게 됩니다.</li>
<li>따라서, `myObj`의 `myProperty`속성을 정확히 참조하여 `"Hello, world!"`를 출력합니다.</li>
</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>lulla-by</summary>
<div>
(1) innerFunc가 왜 undefined를 출력했는지
<br>
콜백 함수 내부에서의 `this`는 콜백함수의 제어권을 가진 함수가 `this`를 어떻게 정했는지에 따라 `this`가 달라집니다. 만약 `this`를 설정하지 않은 상황이라면 콜백함수는 기본적으로 전역 객체를 바라봅니다. 콜백함수 내부에서 `this.myProperty`를 호출했는데 이때 `this`는 전역 객체를 바라봅니다. 따라서 미리 전역 객체에 `myProperty`를 선언 및 할당하지 않는 이상 `undefined`가 출력됩니다.
<br>
<br>
(2) 이 문제를 해결한 방법
<br>
저는 `apply` 메서드를 사용하여 setTimout 내부의 콜백 함수가 `myObj`를 `this`로 바라보도록 설정했습니다.
<pre><code>
const myObj = {
  myProperty: 'Hello, world!',
  outerFunc: function() {
    console.log(this.myProperty); // 'Hello, world!'
    setTimeout(function innerFunc() {
      console.log(this.myProperty); // 'Hello, world!'
    }.apply(this), 1000);
  }
};

myObj.outerFunc();
</code></pre>
</div data-type="detailsContent">
</details>


**출제자 : chaehaeun**
>```js
const myObj = {
  myProperty: 'Hello, world!',
  outerFunc: function() {
    console.log(this.myProperty); // 'Hello, world!'
    setTimeout((function innerFunc() {
      console.log(this.myProperty); // 'Hello, world!'
    }).bind(this), 1000);
  }
};
>
myObj.outerFunc();
```
>
**1. innerFunc가 undefined를 출력한 이유: **<br>
`setTimeout` 내부에서 호출되는 함수는 기본적으로 전역 컨텍스트에서 실행됩니다. 따라서 `this`는 전역 객체를 가리키게 되고, `myObj`와는 무관한 컨텍스트가 되기 때문에 `this.myProperty`는 `undefined`를 반환합니다.
<br>
<br>
**2. 이 문제를 해결한 방법**<br>
`bind`를 사용하여 `innerFunc` 함수의 `this`를 `outerFunc`의 `this`에 명시적으로 바인딩했습니다. `.bind(this)`는 `outerFunc`가 호출될 때의 `this`, 즉 `myObj`를 `innerFunc`의 `this`에 고정시킵니다. 이렇게 하면 `setTimeout` 내부에서 실행되더라도 `innerFunc`의 `this`가 `myObj`를 정확히 가리키게 되어 `this.myProperty`가 정상적으로 'Hello, world!'를 출력하게 됩니다.

<br>

---

<br>

### 3\. [this](https://github.com/Coding-Village-Protector/core-js/issues/14)

#### 다음에서 제시하는 this 관련 단답형 문제에 대해 간단한 답변을 작성해주세요. 책 내용을 바탕으로 간단하게 작성해주세요.
1. this는 언제 결정되나요?
2. 프로그래밍 언어에서 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치입니다. 이 둘을 구분하는 유일한 차이는 무엇일까요? 또한, "함수로서의 호출"과 "메서드로서 호출"을 어떻게 구분하는지 말씀해주세요. 
3. 생성자(클래스)와 인스턴스는 무엇인가요?
4. 화살표 함수의 this는 어떤 특징을 가지고 있나요?

<details data-node-type="hn-details-summary">
<summary>chaehaeun</summary>
<div>
1. 함수나 메서드가 호출될 때 결정됩니다.
<br>
<br>
2. 함수와 메서드의 유일한 차이는 메서드가 클래스의 인스턴스나 객체에 종속되어 있음입니다. "함수로서의 호출"은 독립적으로 호출되며, "메서드로서의 호출"은 객체의 속성으로 호출됩니다.
<br>
<br>
3. 생성자 함수는 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수입니다. 그리고 그 생성자 함수를 통해 만든 객체를 인스턴스라고 합니다.
<br>
<br>
4. 화살표 함수는 자신만의 this가 없기 때문에 언제나 상위 스코프의 this를 참조하는 특징을 가지고 있습니다.
</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>Stilllee</summary>
<div>
1.  자바스크립트에서 `this`는 실행 컨텍스트가 생성될 때 즉, **함수가 호출될 때** 결정되며 어떻게 호출되는지에 따라 `this`의 값이 달라집니다.
<br>
<br>
2. 함수가 변수나 상수에 할당되어 독립적으로 호출되는 것은 **함수로서의 호출**이고, 객체의 프로퍼티에 할당되어 해당 객체의 컨텍스트에서 호출되는 것을 **메서드로서의 호출**입니다.
<br>
<br>
3. **클래스**는 어떤 공통된 성질을 지니는 객체들을 생성하는데 사용하는 함수이고, 클래스를 통해 만든 객체를 **인스턴스**라고 합니다.
<br>
<br>
4. 화살표 함수는 자신만의 `this`를 생성하지 않고, 자신이 생성된 그 스코프의 `this`를 사용합니다. 즉, 화살표 함수 내에서의 함수는 독립적인 기능을 수행하는 반면, 메서드는 객체와 연관된 동작을 수행합니다. `this`는 항상 외부 함수의 `this`와 같습니다.
</div data-type="detailsContent">
</details>

<details data-node-type="hn-details-summary">
<summary>lulla-by</summary>
<div>
1. `this`는 함수를 호출할 때 결정됩니다.
<br>
<br>
2. 둘을 구분하는 차이는 **독립성**입니다. 함수는 함수 그 자체로서 호출되는 것이지만 메서드는 자신을 호출한 대상에 대하여 함수를 실행하게 됩니다. 이 둘을 구분하는 대표적인 방법으로는 .과 대괄호 표기법으로 함수 앞에 자신을 호출한 객체가 있는 경우 메서드가 됩니다.
<br>
<br>
3. `class`는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다. 인스턴스는 생성자 함수를 사용하여 생성된 객체입니다.
<br>
<br>
4. 화살표 함수는 `this` 바인딩의 과정 자체가 생략되어 있습니다. 따라서 내부에 `this`값이 존재하지 않으며 접근하고자 할 경우 스코프체인상 가장 가까운 `this`에 접근하게 됩니다.
</div data-type="detailsContent">
</details>

**출제자 : eeeyooon**
>**1.  this는 언제 결정되나요?**<br>
기본적으로 실행 컨텍스트가 생성될 때 함께 결정됩니다. 실행컨텍스트는 함수를 호출할 때 생성되므로, 바꿔말하면 this는 함수를 호출할 때 결정된다고 할 수 있습니다.
>
**2.  프로그래밍 언어에서 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치입니다. 이 둘을 구분하는 유일한 차이는 무엇일까요? 또한 "함수로서의 호출"과 "메서드로서 호출"을 어떻게 구분하는지 말씀해주세요.**<br>
**독립성**. 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행합니다. 자바스크립트는 상황 별로 this 키워드에 다른 값을 부여하게 함으로써 이를 구현했습니다.
>
‘함수로서 호출’과 ‘메서드로서 호출’을 **점(.)의 유무**로 구별할 수 있습니다. 앞에 점이 없으면 함수로서 호출한 것(`func(1);`)이고, 앞에 점이 있으면 메서드로서 호출한 것(`obj.method(2);`)입니다. 덧붙여, 대괄호 표기법에 따른 경우(`obj[’method’](2)`)도 메서드로서 호출한 것입니다.
>
정리하자면, 점 표기법이든 대괄호 표기법이든 어떤 함수를 호출할 때 그 함수 이름(프로퍼티명) 앞에 객체가 명시되어 있는 경우에는 메서드로 호출한 것이고, 그렇지 않은 모든 경우는 함수로 호출한 것입니다."
>
**3.  생성자(클래스)와 인스턴스는 무엇인가요?**<br>
클래스를 통해 만든 객체를 인스턴스라고 합니다. 생성자는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다. 이 틀에는 해당 클래스의 공통 속성들이 미리 준비되어있고, 여기에 구체적인 인스턴스의 개성을 더해 개별 인스턴스를 만들 수 있습니다.
- 생성자 = 기본 붕어빵 반죽, 굽기에 알맞은 온도와 시간이 설정된 붕어빵 틀
- 인스턴스의 개성 = 피자치즈, 슈크림, 팥
- 개별 인스턴스 = 슈붕, 팥붕, 피붕
>
**4.  화살표 함수의 this는 어떤 특징을 가지고 있나요?**<br>
화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용할 수 있습니다. (ES5 환경에서는 화살표 함수를 사용할 수 X)
