๐ฏ 03. this ๋ฐ์ธ๋ฉ โ '๋๋ ๋๊ตฌ์ธ๊ฐ'๋ฅผ ๊ฒฐ์ ํ๋ 5๊ฐ์ง ๊ท์น
๐ ๊ฐ์
JS์์ ๊ฐ์ฅ ๋ง์ด ํท๊ฐ๋ฆฌ๋ this์ 5๊ฐ์ง ๊ฒฐ์ ๊ท์น, ํ์ดํ ํจ์์ ์ผ๋ฐ ํจ์์ ๊ฒฐ์ ์ ์ฐจ์ด, call/apply/bind ์๋ฒฝ ์ ๋ณต.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
this๊ฐ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ 5๊ฐ์ง ๊ท์น์ ์ค๋ช ํ ์ ์๋ค.- ํ์ดํ ํจ์๊ฐ
this๋ฅผ ๋ฐ์ธ๋ฉํ์ง ์๋ ์ด์ ์ ํ์ฉ๋ฒ์ ์๋ค.call,apply,bind๋กthis๋ฅผ ๋ช ์์ ์ผ๋ก ๊ณ ์ ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ฌด์ ์ ์ฉํ๋ค.
๐ ๋ชฉ์ฐจ
- ๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
- ๐ค 1. ์ ์์์ผ ํ๋๊ฐ?
- ๐ 2. this ๊ฒฐ์ ๊ท์น 5๊ฐ์ง
- โก 3. ํ์ดํ ํจ์ vs ์ผ๋ฐ ํจ์ this ๋น๊ต
- ๐๏ธ 4. ์ค๋ฌด ํจํด
- ๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
- ๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
- ๐ ๋ ์์๋ณด๊ธฐ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 20๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 12๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
[this์ ์ ์ฒด] โ [5๊ฐ์ง ๊ฒฐ์ ๊ท์น] โ [ํ์ดํ ํจ์์ ํน์์ฑ] โ [์ค๋ฌด ์ ์ฉ]
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- "
this๊ฐundefined์ธ๋ฐ์?" ์๋ฌ๋ฅผ ์ฆ์ ์์ธ ํ์ ํ๊ณ ์์ ํ๋ค. - ํด๋์ค ๋ฉ์๋๋ฅผ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ์ธ ๋
this์์ค ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๋ค. -
call,apply,bind๋ฅผ ๊ฐ๊ฐ ์ธ์ ์ฐ๋์ง ๊ตฌ๋ถํ๋ค.
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
๐ฃ ์์ฒ : "์ํธ ๋, ์ ๋๋์ด ํฐ ๋ฌธ์ ๋ฅผ ๋ง๋ฌ์ด์. ์ ์ ํ๋กํ ์ปดํฌ๋ํธ์์ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ํด๋์ค ๋ฉ์๋๋ฅผ ๋๊ฒผ๋๋ฐ...
this.userName์ดundefined์์. ๋ถ๋ช ๋ฉ์๋ ์์this.userName์ด ์๋๋ฐ, ๋ฒํผ ํด๋ฆญํ๋ฉดCannot read properties of undefined๊ฐ ๋ ์.this๊ฐ ๋์ฒด ๋ญ ๊ฐ๋ฆฌํค๋ ๊ฑด์ง ๋ชจ๋ฅด๊ฒ ์ด์. ์ฝ์์this์ฐ์ด๋ดค๋๋undefined๊ฐ ๋์์ด์. ์ด๊ฑฐ React ๋ฒ๊ทธ์ธ๊ฐ์?"
๐ฆ ์ํธ: "React ๋ฒ๊ทธ ์๋์ผ.
this๋ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋๋๋ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๊ฑฐ๋ . ํด๋์ค ๋ฉ์๋๋ฅผ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ๋๊ธฐ๋ฉด, ๊ทธ ๋ฉ์๋๊ฐ ํด๋์ค ์ธ์คํด์ค๊ฐ ์๋ ์ด๋ฒคํธ ์์คํ ์ ์ํด ํธ์ถ ๋ผ. ๊ทธ ์๊ฐthis๋ ํด๋์ค ์ธ์คํด์ค๊ฐ ์๋์ผ. ํ์ดํ ํจ์๋ก ์ ์ธํ๊ฑฐ๋bind๋ก ๊ณ ์ ํ๋ฉด ํด๊ฒฐ๋ผ. ์ค๋this5๊ฐ์ง ๊ท์น ๋ฐฐ์ฐ๋ฉด ์ด ์๋ฌ๋ ์์ํ ๋นํ์ง ์์ ๊ฑฐ์ผ."
๐ค 1. ์ ์์์ผ ํ๋๊ฐ?
์์ฒ ์ด๊ฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์์์ this.nickname ์ ์ถ๋ ฅํ๋ ค๋ค undefined ๊ฐ ํ์ด๋์์ ๋, ์ํธ ๋ฆฌ๋ ๋์ด ๋งํ๋ค: "JS์ this ๋ Java์ฒ๋ผ 'ํ์ฌ ์ธ์คํด์ค'๊ฐ ์๋์ผ. ํธ์ถ ๋ฐฉ์์ด ๊ฒฐ์ ํด." this๋ JS์์ ๊ฐ์ฅ ์คํด๊ฐ ๋ง์ ํค์๋ ๋ค. ๋ค๋ฅธ ์ธ์ด(Java, C#)์์๋ this๊ฐ ํญ์ ํ์ฌ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค์ง๋ง, JS์ this๋ ํธ์ถ ๋ฐฉ์ ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
JS์
this๋ ํจ์๊ฐ ์ ์ธ๋ ์์น๊ฐ ์๋๋ผ, ํจ์๊ฐ ํธ์ถ๋ ๋ฐฉ์์ ์ํด ๊ฒฐ์ ๋๋ค.
์ด ์ฌ์ค ํ๋๋ฅผ ์ดํดํ๋ ๊ฒ๋ง์ผ๋ก๋ ์๋ง์ "์ this๊ฐ ์ด์ํด?" ๋ฒ๊ทธ๋ฅผ ์๋ฐฉํ ์ ์๋ค.
๐ 2. this ๊ฒฐ์ ๊ท์น 5๊ฐ์ง
๊ท์น 1: ์ ์ญ ์ปจํ ์คํธ
์ด๋ค ํจ์์๋ ์ํ์ง ์์ ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ, ์ฆ ์ ์ญ ๊ณต๊ฐ์์ this๋ฅผ ๋ถ๋ฅด๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ํ๊ฒฝ์ ๋ฐ๋ผ ๊ทธ ์ ์ฒด๊ฐ ์กฐ๊ธ์ฉ ๋ฌ๋ผ์ง๋๋ค.
// ๋ธ๋ผ์ฐ์ ํ๊ฒฝ
console.log(this); // window ๊ฐ์ฒด
// strict mode ('use strict')
"use strict";
function showThis() {
console.log(this); // undefined (strict mode์์๋ ์ ์ญ ๋ฐ์ธ๋ฉ ์์)
}
showThis();
// Node.js ํ๊ฒฝ
console.log(this); // {} (๋น module.exports ๊ฐ์ฒด)๊ท์น 2: ๋ฉ์๋ ํธ์ถ
๊ฐ์ฅ ํํ๊ฒ ์ ํ๋ ์ํฉ์
๋๋ค. ๊ฐ์ฒด์ ์ด๋ฆํ๋ฅผ ๋ฌ๊ณ ๋ฉ์๋๋ก ํธ์ถ๋ ๋, this๋ ์๊ธฐ๋ฅผ ๋ถ๋ฌ์ค ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ์์๋ค ์ปค๋ฎค๋ํฐ์ ์ ์ ๊ฐ์ฒด๋ก ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
// ์์๋ค ์ปค๋ฎค๋ํฐ โ ์ ์ ๊ฐ์ฒด
const user = {
name: "์์ฒ ",
role: "junior",
greet() {
console.log(`์๋
ํ์ธ์, ์ ๋ ${this.name}์ด์์!`); // this โ user ๊ฐ์ฒด
},
getRole: function () {
return this.role; // this โ user ๊ฐ์ฒด
},
};
user.greet(); // "์๋
ํ์ธ์, ์ ๋ ์์ฒ ์ด์์!"
user.getRole(); // "junior"
// โ ๋ฉ์๋๋ฅผ ๋ณ์์ ๊บผ๋ด๋ ์๊ฐ this ์์ค
const greetFn = user.greet;
greetFn(); // "์๋
ํ์ธ์, ์ ๋ undefined์ด์์!" โ this๊ฐ ์ ์ญ(๋๋ undefined)์ผ๋ก ๋ฐ๋!ํต์ฌ:
๊ฐ์ฒด.๋ฉ์๋()ํํ๋ก ํธ์ถํ ๋๋งthis๊ฐ ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ๋ฉ์๋๋ฅผ ๋ฝ์์ ๋ฐ๋ก ํธ์ถ ํ๋ ์๊ฐ,this๋ ์์ด๋ฒ๋ฆฐ๋ค.
๊ท์น 3: ์์ฑ์ ํจ์ (new)
new ํค์๋๋ฅผ ๋ถ์ฌ ํจ์๋ฅผ ํธ์ถํ๋ ์๊ฐ, ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ด๋ถ์ ์๋ก์ด ๋น ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ this๋ฅผ ๊ทธ๊ณณ์ผ๋ก ์ฐ๊ฒฐํฉ๋๋ค.
function User(name, role) {
// new๋ก ํธ์ถ ์, this = {} (์๋ก ์์ฑ๋ ๊ฐ์ฒด)
this.name = name;
this.role = role;
// ์๋ฌต์ ์ผ๋ก return this;
}
const yc = new User("์์ฒ ", "junior");
const yh = new User("์ํธ", "lead");
console.log(yc.name); // "์์ฒ "
console.log(yh.role); // "lead"
// new ์์ด ํธ์ถํ๋ฉด?
const broken = User("์์ฒ ", "junior"); // this = window (๋ธ๋ผ์ฐ์ ) โ ์ ์ญ ์ค์ผ!
console.log(broken); // undefined (return ์์)๊ท์น 4: ๋ช ์์ ๋ฐ์ธ๋ฉ (call/apply/bind)
์์ง์๊ฒ "์ค๋ this๋ ์ด ์น๊ตฌ์ผ!"๋ผ๊ณ ์ง์ ์ฃผ์
ํ๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ๋ค์
๋๋ค.
function introduce(greeting, punctuation) {
console.log(`${greeting}, ์ ๋ ${this.name}์
๋๋ค${punctuation}`);
}
const yc = { name: "์์ฒ " };
const yh = { name: "์ํธ" };
// call โ ์ธ์๋ฅผ ์ฝค๋ง๋ก ๋์ด, ์ฆ์ ์คํ
introduce.call(yc, "์๋
ํ์ธ์", "!"); // "์๋
ํ์ธ์, ์ ๋ ์์ฒ ์
๋๋ค!"
introduce.call(yh, "๋ฐ๊ฐ์ต๋๋ค", "~"); // "๋ฐ๊ฐ์ต๋๋ค, ์ ๋ ์ํธ์
๋๋ค~"
// apply โ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก, ์ฆ์ ์คํ
introduce.apply(yc, ["์๋
ํ์ธ์", "!"]); // "์๋
ํ์ธ์, ์ ๋ ์์ฒ ์
๋๋ค!"
// bind โ this๋ฅผ ๊ณ ์ ํ ์ ํจ์๋ฅผ ๋ฐํ (์ฆ์ ์คํ ์ ํจ)
const introduceyc = introduce.bind(yc, "์๋
ํ์ธ์");
introduceyc("!"); // "์๋
ํ์ธ์, ์ ๋ ์์ฒ ์
๋๋ค!"
introduceyc("~"); // "์๋
ํ์ธ์, ์ ๋ ์์ฒ ์
๋๋ค~"
// yc๋ก this๊ฐ ์๊ตฌ ๊ณ ์ ๋จ| ๋ฉ์๋ | ํธ์ถ ๋ฐฉ์ | ์ธ์ ์ ๋ฌ | ์ฌ์ฉ ์์ |
|---|---|---|---|
call | ์ฆ์ ์คํ | ๋์ด | ์ง๊ธ ๋น์ฅ ์คํํ ๋ |
apply | ์ฆ์ ์คํ | ๋ฐฐ์ด | ์ธ์๊ฐ ๋ฐฐ์ด๋ก ์์ ๋ |
bind | ํจ์ ๋ฐํ | ๋์ด (์ ํ) | ๋์ค์ ์คํํ ํจ์๊ฐ ํ์ํ ๋ |
๊ท์น 5: ํ์ดํ ํจ์ โ this๊ฐ ์๋ค
ํ์ดํ ํจ์๋ ์ด๊ธฐ์ ์ด์ง ์์ต๋๋ค. ์์ ๋ง์ this๋ฅผ ๊ณ ์งํ์ง ์๊ณ , **์์ ์ด ํ์ด๋ ๊ณณ์ this**๋ฅผ ๊ทธ๋๋ก ๋ฌผ๋ ค๋ฐ์ ์ฌ์ฉํฉ๋๋ค. ์ํธ ๋ฆฌ๋ ๋์ด "๋ ์์ปฌ this๋ฅผ ์ดํดํ๋ฉด ์ฝ๋ฐฑ ํจ์๊ฐ ์ฌ์์ง๋ค"๊ณ ํ ์ด์ ๊ฐ ๋ฐ๋ก ์ด๊ฒ์
๋๋ค.
const user = {
name: "์์ฒ ",
friends: ["์ํธ", "์์", "์์"],
// โ ์ผ๋ฐ ํจ์ โ forEach ์ฝ๋ฐฑ์์ this ์์ค
listFriendsWrong() {
this.friends.forEach(function (friend) {
// ์ด ์ฝ๋ฐฑ์ ๋
๋ฆฝ์ ์ผ๋ก ํธ์ถ๋จ โ this๋ undefined (strict mode)
console.log(`${this.name}์ ์น๊ตฌ: ${friend}`); // TypeError!
});
},
// โ
ํ์ดํ ํจ์ โ ์์ ์ค์ฝํ(listFriendsRight ๋ฉ์๋)์ this๋ฅผ ๋ฌผ๋ ค๋ฐ์
listFriendsRight() {
this.friends.forEach((friend) => {
// ํ์ดํ ํจ์ โ this = user ๊ฐ์ฒด (์์ this ๊ทธ๋๋ก)
console.log(`${this.name}์ ์น๊ตฌ: ${friend}`); // โ
});
},
};
user.listFriendsWrong(); // TypeError
user.listFriendsRight(); // "์์ฒ ์ ์น๊ตฌ: ์ํธ", "์์ฒ ์ ์น๊ตฌ: ์์", ...โก 3. ํ์ดํ ํจ์ vs ์ผ๋ฐ ํจ์ this ๋น๊ต
์คํ๋์์ ์์ฒ ์ด๊ฐ ๊ฒช์ ๋ฒ๊ทธ์ ์ ์ฒด๊ฐ ๋ฐ๋ก ์ด๊ฒ์ด๋ค. ๊ฐ์ ๊ฐ์ฒด์ ๋ฉ์๋์์ setTimeout ์ ํธ์ถํ ๋, ์ผ๋ฐ ํจ์ ์ฝ๋ฐฑ์ this ๋ฅผ ์์ด๋ฒ๋ฆฌ์ง๋ง ํ์ดํ ํจ์๋ ์ ์ธ๋ ์์ ์ this ๋ฅผ ๊ทธ๋๋ก ์ ์งํ๋ค. ์ด ์ฐจ์ด ํ๋๊ฐ ์๋ง์ ๋ฐํ์ ์๋ฌ์ ์์ธ์ด ๋๋ค.
// ์์๋ค ์ปค๋ฎค๋ํฐ โ ์ค์๊ฐ ์๋ฆผ ํ์ด๋จธ
const notificationService = {
message: "์ ๊ฒ์๊ธ์ด ์์ต๋๋ค!",
delay: 1000,
// โ ์ผ๋ฐ ํจ์ โ this ์์ค
startWrong() {
setTimeout(function () {
console.log(this.message); // undefined โ setTimeout์ด ์ ์ญ์์ ํธ์ถ
}, this.delay);
},
// โ
ํ์ดํ ํจ์ โ ๋ ์์ปฌ this ์ ์ง
startRight() {
setTimeout(() => {
console.log(this.message); // "์ ๊ฒ์๊ธ์ด ์์ต๋๋ค!" โ notificationService์ this ์ ์ง
}, this.delay);
},
// โ
bind โ ๋ช
์์ ๊ณ ์
startWithBind() {
setTimeout(
function () {
console.log(this.message);
}.bind(this),
this.delay
);
},
};
notificationService.startWrong(); // undefined
notificationService.startRight(); // "์ ๊ฒ์๊ธ์ด ์์ต๋๋ค!"
notificationService.startWithBind(); // "์ ๊ฒ์๊ธ์ด ์์ต๋๋ค!"โ ๏ธ ํ์ดํ ํจ์๊ฐ ์ ์ ํ์ง ์์ ๊ฒฝ์ฐ:
- ๊ฐ์ฒด์ ๋ฉ์๋๋ก ์ง์ ์ ์ํ ๋ (๊ฐ์ฒด๋ฅผ this๋ก ์ก์ง ๋ชปํจ)
prototype์ ๊ณตํต ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ๋- ์์ฑ์ ํจ์๋ก ์ฌ์ฉํ ๋ (
new์ฌ์ฉ ๋ถ๊ฐ)
์ํธ ๋ฆฌ๋ ๋์ด ์ค์ํ๊ธฐ ์ฌ์ด ํฌ์ธํธ๋ผ๋ฉฐ ์ฐ์ด์ค ์์์ ๋๋ค. ํ์ดํ ํจ์๋ฅผ ๋ฉ์๋๋ก ์ผ์ ๋ ์ด๋ค ์ผ์ด ๋ฒ์ด์ง๋์ง ๋ณด์ธ์.
// โ ํ์ดํ ํจ์๋ฅผ ๊ฐ์ฒด ๋ฉ์๋๋ก โ this ์์ค
const post = {
title: "ํด๋ก์ ์์ ์ ๋ณต",
getTitle: () => {
return this.title; // this โ ์ ์ญ (undefined)
},
};
post.getTitle(); // undefined โ ์๋์ ๋ค๋ฆ!
// โ
๊ฐ์ฒด ๋ฉ์๋๋ ์ผ๋ฐ ํจ์ (๋จ์ถ ๋ฉ์๋ ์ฌ์ฉ ๊ถ์ฅ)
const post2 = {
title: "ํด๋ก์ ์์ ์ ๋ณต",
getTitle() {
return this.title; // this โ post2 ๊ฐ์ฒด
},
};
post2.getTitle(); // "ํด๋ก์ ์์ ์ ๋ณต" โ
๐๏ธ 4. ์ค๋ฌด ํจํด
์ํธ ๋ฆฌ๋ ๋์ด ์์ฒ ์ด PR์ ๋จ๊ธด ๋ฆฌ๋ทฐ์์ ์ ์ํ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด๋ค. ํด๋์ค ๋ฉ์๋๋ฅผ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ๋๊ธธ ๋ this ๊ฐ ์์ค๋๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ํจํด์ ๋น๊ตํ๋ค. ์์ฑ์์์ bind ํ๋ ๋ฐฉ๋ฒ ๊ณผ ํด๋์ค ํ๋ ํ์ดํ ํจ์ ๋ฅผ ์ฌ์ฉํ๋ ํ๋์ ๋ฐฉ๋ฒ ์ค, ํ ์ปจ๋ฒค์
์ ๋ง๋ ๋ฐฉ์์ ์ผ๊ด๋๊ฒ ์ ํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
// ์์๋ค ์ปค๋ฎค๋ํฐ โ ํด๋์ค ๊ธฐ๋ฐ ์ปดํฌ๋ํธ์์ this ๊ณ ์
class CommentForm {
constructor(postId) {
this.postId = postId;
this.content = "";
// ๋ฐฉ๋ฒ 1: bind๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ this ๊ณ ์
this.handleSubmit = this.handleSubmit.bind(this);
document.getElementById("submit-btn").addEventListener("click", this.handleSubmit);
}
handleSubmit(event) {
event.preventDefault();
console.log(`๊ฒ์๊ธ ${this.postId}์ ๋๊ธ ์ ์ก: ${this.content}`);
// bind ์์ผ๋ฉด this.postId โ undefined
}
}
// ๋ฐฉ๋ฒ 2 (๋ ํ๋์ ): ํด๋์ค ํ๋ + ํ์ดํ ํจ์๋ก ์๋ ๋ฐ์ธ๋ฉ
class CommentFormModern {
constructor(postId) {
this.postId = postId;
this.content = "";
}
// ํด๋์ค ํ๋๋ก ์ ์ธ๋ ํ์ดํ ํจ์ โ this๊ฐ ์ธ์คํด์ค๋ก ์๋ ๊ณ ์
handleSubmit = (event) => {
event.preventDefault();
console.log(`๊ฒ์๊ธ ${this.postId}์ ๋๊ธ ์ ์ก: ${this.content}`);
};
}
// React์์์ ๊ด์ฉ์ ํจํด
// function Component() {
// const handleClick = () => { ... }; // ํ์ดํ ํจ์๋ก this ๊ฑฑ์ ์์
// return <button onClick={handleClick}>ํด๋ฆญ</button>;
// }๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. ์๋ ์ฝ๋์์ ๊ฐ console.log์ ์ถ๋ ฅ๊ฐ์ ์์ธกํ๋ผ.
const obj = {
value: 42,
getValue() {
return this.value;
},
getValueArrow: () => {
return this.value;
},
};
console.log(obj.getValue()); // ?
console.log(obj.getValueArrow()); // ?
const extracted = obj.getValue;
console.log(extracted()); // ?โ
์ ๋ต: 42, undefined, undefined
๐ก ์์ธ ํด์ค:
obj.getValue(): ๋ฉ์๋ ํธ์ถ โthis = objโobj.value = 42โobj.getValueArrow(): ํ์ดํ ํจ์๋ ์ ์ธ๋ ์์น(์ ์ญ)์this๋ฅผ ์ฌ์ฉ โthis = window/undefinedโundefinedextracted(): ๋ฉ์๋๋ฅผ ๋ฝ์ ์ผ๋ฐ ํจ์๋ก ํธ์ถ โthis = undefined(strict mode) ๋๋windowโundefined- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "์ (.)์ ์ผ์ชฝ์ด this๋ค. ์ ์ด ์์ผ๋ฉด this๋ ์ ์ญ์ด๊ฑฐ๋ undefined๋ค."
Q2. call, apply, bind์ ์ฐจ์ด๋ฅผ ํ ๋ฌธ์ฅ์ฉ ์ค๋ช
ํ๋ผ.
โ ์ ๋ต:
call: this์ ์ธ์๋ฅผ ์ง์ ํด ์ฆ์ ์คํapply: this์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ์ง์ ํด ์ฆ์ ์คํbind: this๊ฐ ๊ณ ์ ๋ ์ ํจ์๋ฅผ ๋ฐํ (์คํ ์ ํจ)
๐ก ์์ธ ํด์ค:
- ์
๋ค
this๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ ๋ฉ์๋์ง๋ง, ์คํ ์์ ๊ณผ ์ธ์ ์ ๋ฌ ๋ฐฉ์ ์ด ๋ค๋ฅด๋ค. - ์ค๋ฌด์์
bind๊ฐ ๊ฐ์ฅ ๋ง์ด ์ฐ์ธ๋ค: ์ด๋ฒคํธ ๋ฆฌ์ค๋, ์ฝ๋ฐฑ, setTimeout ๋ฑ "๋์ค์ ์คํ"๋๋ ํจ์์ this๋ฅผ ๋ฏธ๋ฆฌ ๊ณ ์ ํ ๋. apply๋ ๊ฐ๋ณ ์ธ์ ๋ฐฐ์ด์ ๊ทธ๋๋ก ๋๊ธธ ๋ ์ ์ฉ:Math.max.apply(null, [1, 2, 3])(์์ฆ์ ์คํ๋ ๋Math.max(...arr)๋ก ๋์ฒด).- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "call์ ์ฝค๋ง(comma), apply๋ array, bind๋ ๋ฐํ(bound)"
Q3. ์์ฒ ์ด์ ํ ์คํธ ํ์ โ ์ค๋ฌด ๋๋ ๋ง
์์ฒ ์ด๊ฐ React ํด๋์ค ์ปดํฌ๋ํธ(๋ ๊ฑฐ์)๋ฅผ ์ ์ง๋ณด์ํ๋ ์ค, ๋ฒํผ ํด๋ฆญ ์
this.setState๊ฐundefined๋ผ๋ ์๋ฌ๋ฅผ ๋ฐ๊ฒฌํ๋ค. ์ด๋๊ฐ ๋ฌธ์ ์ด๊ณ , ์ด๋ป๊ฒ ๊ณ ์ณ์ผ ํ๋๊ฐ?
class PostList extends React.Component {
constructor(props) {
super(props);
this.state = { posts: [] };
}
fetchPosts() {
// ํด๋ฆญ ์ this๊ฐ ๋ฌด์์ธ์ง๊ฐ ๋ฌธ์
fetch("/api/posts")
.then((res) => res.json())
.then((data) => this.setState({ posts: data })); // ์ฌ๊ธฐ์ ์๋ฌ
}
render() {
return <button onClick={this.fetchPosts}>๊ฒ์๊ธ ๋ถ๋ฌ์ค๊ธฐ</button>;
}
}โ
์ ๋ต: onClick={this.fetchPosts} โ ๋ฉ์๋๋ฅผ ๊บผ๋ด์ด ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ๋๊ธฐ๋ ์๊ฐ this๊ฐ ์์ค๋๋ค. bind ๋๋ ํ์ดํ ํจ์ ํด๋์ค ํ๋๋ก ํด๊ฒฐํ๋ค.
๐ก ์์ธ ํด์ค:
this.fetchPosts๋ฅผonClick์ ๋๊ธฐ๋ ๊ฒ์const fn = this.fetchPosts์ ๊ฐ๋ค. ์ด ํจ์๊ฐ ํด๋ฆญ ์ด๋ฒคํธ์ ์ํด ํธ์ถ๋ ๋๋PostList์ธ์คํด์ค๊ฐ ์๋ ์ด๋ฒคํธ ์์คํ ์ ์ปจํ ์คํธ์์ ์คํ๋๋ค.- ํด๊ฒฐ ๋ฐฉ๋ฒ 1 (constructor bind):
constructor(props) { super(props); this.fetchPosts = this.fetchPosts.bind(this); // ์์ฑ์์์ ๊ณ ์ } - ํด๊ฒฐ ๋ฐฉ๋ฒ 2 (ํด๋์ค ํ๋ ํ์ดํ ํจ์):
fetchPosts = () => { // this๊ฐ ์ธ์คํด์ค๋ก ์๋ ๊ณ ์ fetch("/api/posts")... } - ํด๊ฒฐ ๋ฐฉ๋ฒ 3 (์ธ๋ผ์ธ ํ์ดํ ํจ์, ์ฑ๋ฅ ์ฃผ์):
<button onClick={() => this.fetchPosts()}> - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "React์์ ํด๋์ค ๋ฉ์๋๋ฅผ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ๋๊ธธ ๋ ๋ฐ๋์ this๋ฅผ ๊ณ ์ ํด๋ผ. ํ์ดํ ํด๋์ค ํ๋๊ฐ ๊ฐ์ฅ ๊น๋ํ๋ค."
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋ this ์์ ํ ์ ๋ณตํ ๊ฒ ๊ฐ๋ค. ์ฌ์ค ์์ ์ this๊ฐ undefined๋ผ๋ ์๋ฌ ๋ณด๋ฉด ๋ฌด์์ .bind(this) ๋ถ์ด๊ฑฐ๋ ํ์ดํ ํจ์๋ก ๊ฐ์๋๋ฐ, ์ด์ ๋ ์ ๊ทธ๋ ๊ฒ ํด์ผ ํ๋์ง๊ฐ ์ดํด๋๋ค.
"์ ์ ์ผ์ชฝ์ด this๋ค" โ ์ํธ ๋์ด ์ด ํ ๋ง๋๋ก ์ ๋ฆฌํด์คฌ์ ๋ ์ง์ง ๋์ ๋ฐํ๋ค. ์์ผ๋ก this ์๋ฌ ๋๋ฉด ์ฝ ์คํ์์ ์ด๋ป๊ฒ ํธ์ถ๋๋์ง ๋จผ์ ํ์ธํ๋ฉด ๋๊ฒ ๋ค.
๐ก ์ค๋์ ๊ตํ: "
this๋ ํจ์๊ฐ ์ด๋ป๊ฒ '๋ถ๋ ธ๋๋'๋ฅผ ๊ธฐ์ตํฉ๋๋ค. ๋๋ฅผ ๋ถ๋ฌ์ค ์ฃผ์ฒด๊ฐ ๊ณงthis์ ๋๋ค. ๋ง์ฝ ์ฃผ์ฒด ์์ด ํ๋ก ๋ถ๋ ธ๋ค๋ฉด, ์ ์ญ ๊ณต๊ฐ์ด๋undefined๋ฅผ ๋ ์ฌ๋ฆฌ์ธ์."
ํด๊ทผํ๊ณ ์ง์์ ๋ผ๋ฉด ๋์ฌ๋จน์ผ๋ฉด์ ๋ค์ ์ฑํฐ ํ์ด๋ด์ผ์ง. ํ๋กํ ํ์ ์ด๋ผ๋... ๋ญ๊ฐ ์ด๋ ค์ธ ๊ฒ ๊ฐ์ ์ด๋ฆ์ธ๋ฐ. ๊ทธ๋๋ ์ด๋ฒ ๊ธฐ์ธ ์ ์งํ๋ฉด ์ด๋ป๊ฒ๋ ๋๊ฒ ์ง. ํ์ดํ !