![[3장] this - 북 스터디](https://cdn.hashnode.com/res/hashnode/image/upload/v1709697986775/42dd439c-c3a5-4953-bee8-e1fea35fe738.png)
코딩 마을 방범대 : 3장. this
질문과 답변
1. 함수 내부의 this 바인딩을 변경하는 방법
함수 내부의 this 바인딩을 변경하는 방법
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를 바라보게 하려면 어떻게 해야할까요?
여러 방법 중 한 가지를 선택하고 예시코드와 함께 설명해주세요.
chaehaeun
c를 화살표 함수로 정의하게 되면 c 함수 내부의 this가 obj 객체를 가리키게 됩니다.
var a = "global!";
var obj = {
a: "object!",
b: function() {
console.log(this.a);
const c = () => {
console.log(this.a);
}
c();
}
}
obj.b();
화살표 함수는 자신만의 this를 가지지 않기 때문에 자신이 선언된 렉시컬 스코프의 this 값을 상속 받습니다. 따라서 화살표 함수로 선언된 c는 b의 this를 상속 받아 obj를 가리키게 됩니다.
eeeyooon
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();
lulla-by
bind 메서드를 활용하는 방법을 설명해주셔서 저는 변수를 활용하여 우회하는 케이스로 접근해봤습니다.
해당 방식은 es5까지 자체적으로 내부 함수에
this를 상속할 방법이 없을 때 사용한 방식으로 살짝 허무하지만 기대한대로 작동합니다.
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();
출제자 : Stilllee
1. 변수명을 이용한 우회
this를 다른 변수에 할당하고 내부 함수에서 이 변수를 사용하는 방식으로,this의 값이 함수가 선언될 때 결정되는 것을 활용합니다. 일반적으로는self,that,_this,_등의 변수명을 사용합니다.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();
2. 화살표 함수
ES6에서 도입된 화살표 함수는 자체적인this바인딩을 갖지 않고, 상위 스코프의this를 그대로 사용합니다.var a = "global!"; var obj = { a: "object!", b: function() { console.log(this.a); // object! const c = () => { console.log(this.a); // object! } c(); } } obj.b();
3.
call/apply메서드
call또는apply메서드를 사용하여 함수를 호출하면서this값을 명시적으로 바인딩 할 수 있습니다.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();
4.
bind메서드
bind메서드를 사용하여 함수의this를 고정시킬 수 있습니다. 이렇게 하면 함수가 어디에서 호출되더라도this는bind에 전달된 객체를 가리킵니다.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();
2. 메서드의 this와 메서드 내부의 콜백 함수의 this
메서드의 this와 메서드 내부 콜백 함수의 this 불일치 문제를 해결 후 설명해주세요.
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)이 문제를 해결한 방법, 두 가지에 대해 설명해주세요.
eeeyooon
const myObj = {
myProperty: 'Hello, world!',
outerFunc: function() {
console.log(this.myProperty); // 'Hello, world!'
setTimeout(() => { //
console.log(this.myProperty); // 'Hello, world!'
}, 1000);
}
};
myObj.outerFunc();
(1) 기존 코드 innerFunc에서 this.myProperty가 undefined를 출력한 이유는 setTimeout에 의해 호출된 일반 함수 내에서의 this는 전역 객체를 가리키기 때문입니다. 이때 myProperty는 전역 객체가 아니기 때문에 undefined가 됩니다.
(2) setTimeout의 콜백 함수를 일반 함수(innerFunc)에서 화살표 함수로 변경하여 해결했습니다. 이 화살표 함수는 outFunc의 this를 상속받으므로, this.myProperty는 myObj의 myProperty를 참조하게 됩니다.
Stilllee
innerFunc에서 undefined 출력의 이유innerFunc는 setTimeout내의 콜백 함수로 사용되었습니다. setTimeout과 같은 내장 함수 내에서 일반 함수로 호출되는 콜백함수의 this는 기본적으로 전역 컨텍스트를 가리킵니다.myProperty라는 이름의 속성이 존재하지 않기 때문에 undefined를 반환하는 것입니다.(2) :
bind메서드로 문제 해결
const myObj = {
myProperty: "Hello, world!",
outerFunc: function () {
console.log(this.myProperty);
setTimeout(
function innerFunc() {
console.log(this.myProperty);
}.bind(this),
1000
);
},
};
myObj.outerFunc();
bind메서드를 사용하여 innerFunc의 this를 outerFunc의 this인 myObj객체로 명시적으로 설정했습니다..bind(this)를 호출함으로써 innerFunc내의 this는 항상 outerFunc가 호출될 때의 컨텍스트인 myObj객체를 가리키게 됩니다.myObj의 myProperty속성을 정확히 참조하여 "Hello, world!"를 출력합니다.lulla-by
콜백 함수 내부에서의
this는 콜백함수의 제어권을 가진 함수가 this를 어떻게 정했는지에 따라 this가 달라집니다. 만약 this를 설정하지 않은 상황이라면 콜백함수는 기본적으로 전역 객체를 바라봅니다. 콜백함수 내부에서 this.myProperty를 호출했는데 이때 this는 전역 객체를 바라봅니다. 따라서 미리 전역 객체에 myProperty를 선언 및 할당하지 않는 이상 undefined가 출력됩니다.
(2) 이 문제를 해결한 방법
저는
apply 메서드를 사용하여 setTimout 내부의 콜백 함수가 myObj를 this로 바라보도록 설정했습니다.
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();
출제자 : chaehaeun
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를 출력한 이유:
setTimeout내부에서 호출되는 함수는 기본적으로 전역 컨텍스트에서 실행됩니다. 따라서this는 전역 객체를 가리키게 되고,myObj와는 무관한 컨텍스트가 되기 때문에this.myProperty는undefined를 반환합니다.
2. 이 문제를 해결한 방법
bind를 사용하여innerFunc함수의this를outerFunc의this에 명시적으로 바인딩했습니다..bind(this)는outerFunc가 호출될 때의this, 즉myObj를innerFunc의this에 고정시킵니다. 이렇게 하면setTimeout내부에서 실행되더라도innerFunc의this가myObj를 정확히 가리키게 되어this.myProperty가 정상적으로 'Hello, world!'를 출력하게 됩니다.
3. this
다음에서 제시하는 this 관련 단답형 문제에 대해 간단한 답변을 작성해주세요. 책 내용을 바탕으로 간단하게 작성해주세요.
- this는 언제 결정되나요?
- 프로그래밍 언어에서 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치입니다. 이 둘을 구분하는 유일한 차이는 무엇일까요? 또한, "함수로서의 호출"과 "메서드로서 호출"을 어떻게 구분하는지 말씀해주세요.
- 생성자(클래스)와 인스턴스는 무엇인가요?
- 화살표 함수의 this는 어떤 특징을 가지고 있나요?
chaehaeun
2. 함수와 메서드의 유일한 차이는 메서드가 클래스의 인스턴스나 객체에 종속되어 있음입니다. "함수로서의 호출"은 독립적으로 호출되며, "메서드로서의 호출"은 객체의 속성으로 호출됩니다.
3. 생성자 함수는 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수입니다. 그리고 그 생성자 함수를 통해 만든 객체를 인스턴스라고 합니다.
4. 화살표 함수는 자신만의 this가 없기 때문에 언제나 상위 스코프의 this를 참조하는 특징을 가지고 있습니다.
Stilllee
this는 실행 컨텍스트가 생성될 때 즉, 함수가 호출될 때 결정되며 어떻게 호출되는지에 따라 this의 값이 달라집니다.
2. 함수가 변수나 상수에 할당되어 독립적으로 호출되는 것은 함수로서의 호출이고, 객체의 프로퍼티에 할당되어 해당 객체의 컨텍스트에서 호출되는 것을 메서드로서의 호출입니다.
3. 클래스는 어떤 공통된 성질을 지니는 객체들을 생성하는데 사용하는 함수이고, 클래스를 통해 만든 객체를 인스턴스라고 합니다.
4. 화살표 함수는 자신만의
this를 생성하지 않고, 자신이 생성된 그 스코프의 this를 사용합니다. 즉, 화살표 함수 내에서의 함수는 독립적인 기능을 수행하는 반면, 메서드는 객체와 연관된 동작을 수행합니다. this는 항상 외부 함수의 this와 같습니다.
lulla-by
this는 함수를 호출할 때 결정됩니다.
2. 둘을 구분하는 차이는 독립성입니다. 함수는 함수 그 자체로서 호출되는 것이지만 메서드는 자신을 호출한 대상에 대하여 함수를 실행하게 됩니다. 이 둘을 구분하는 대표적인 방법으로는 .과 대괄호 표기법으로 함수 앞에 자신을 호출한 객체가 있는 경우 메서드가 됩니다.
3.
class는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다. 인스턴스는 생성자 함수를 사용하여 생성된 객체입니다.
4. 화살표 함수는
this 바인딩의 과정 자체가 생략되어 있습니다. 따라서 내부에 this값이 존재하지 않으며 접근하고자 할 경우 스코프체인상 가장 가까운 this에 접근하게 됩니다.
출제자 : eeeyooon
1. this는 언제 결정되나요?
기본적으로 실행 컨텍스트가 생성될 때 함께 결정됩니다. 실행컨텍스트는 함수를 호출할 때 생성되므로, 바꿔말하면 this는 함수를 호출할 때 결정된다고 할 수 있습니다.2. 프로그래밍 언어에서 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치입니다. 이 둘을 구분하는 유일한 차이는 무엇일까요? 또한 "함수로서의 호출"과 "메서드로서 호출"을 어떻게 구분하는지 말씀해주세요.
독립성. 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행합니다. 자바스크립트는 상황 별로 this 키워드에 다른 값을 부여하게 함으로써 이를 구현했습니다.‘함수로서 호출’과 ‘메서드로서 호출’을 점(.)의 유무로 구별할 수 있습니다. 앞에 점이 없으면 함수로서 호출한 것(
func(1);)이고, 앞에 점이 있으면 메서드로서 호출한 것(obj.method(2);)입니다. 덧붙여, 대괄호 표기법에 따른 경우(obj[’method’](2))도 메서드로서 호출한 것입니다.정리하자면, 점 표기법이든 대괄호 표기법이든 어떤 함수를 호출할 때 그 함수 이름(프로퍼티명) 앞에 객체가 명시되어 있는 경우에는 메서드로 호출한 것이고, 그렇지 않은 모든 경우는 함수로 호출한 것입니다."
3. 생성자(클래스)와 인스턴스는 무엇인가요?
클래스를 통해 만든 객체를 인스턴스라고 합니다. 생성자는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다. 이 틀에는 해당 클래스의 공통 속성들이 미리 준비되어있고, 여기에 구체적인 인스턴스의 개성을 더해 개별 인스턴스를 만들 수 있습니다.
- 생성자 = 기본 붕어빵 반죽, 굽기에 알맞은 온도와 시간이 설정된 붕어빵 틀
- 인스턴스의 개성 = 피자치즈, 슈크림, 팥
- 개별 인스턴스 = 슈붕, 팥붕, 피붕
4. 화살표 함수의 this는 어떤 특징을 가지고 있나요?
화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용할 수 있습니다. (ES5 환경에서는 화살표 함수를 사용할 수 X)

