๋ค์ด๊ฐ๋ฉด์
๋๋ถ๋ถ์ ์ฐธ๊ณ ์์ ์์ this๋ฅผ ๋ค๋ฃฐ ๋ ํจ์์ ํธ์ถ ๋ฐฉ์์ ๋ํ ์ด์ผ๊ธฐ์ ํจ๊ป this๋ฅผ ์ค๋ช ํ์ฃ . this๋ฅผ ์๊ณ ์ถ์๋ฐ ์๊พธ๋ง ํจ์์ ํธ์ถ ๋ฐฉ์์ ์ด์ผ๊ธฐ ํฉ๋๋ค. ํจ์ ํน์ ํจ์ ํธ์ถ์ด ์ ์ค์ํ ๊น์?
์๋ฐ์คํฌ๋ฆฝํธ์์ ํจ์์ ํจ์ํ ์ธ์ดํน์ง์ด ์ค์ํ ์ด์ ์ค ํ๋๋ ํจ์๊ฐ ์คํ์ ๊ธฐ๋ณธ ๋ชจ๋ ๋จ์์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๋งํฌ์ ์ด ํ๊ฐ๋๋๋์ ์คํ๋๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์ ์ธํ๋ฉด,(์น) ํ์ด์ง์์ ์๋ํ๋๋ก ๋ง๋ค์ด์ง ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ ํจ์์์์ ์คํ ๋ ๊ฒ์ด๋ค. Secrets of the JavaScript Ninja ์ฑ ์ธ์ฉ
์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋๋ ํจ์ํธ์ถ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ์คํ๋ฉ๋๋ค. ํจ์๊ฐ ํธ์ถ ๋๋ ๋ฐฉ์์ ์ฝ๋ ์๋ ๋ฐฉ์์ ์ํฅ์ ๋ฏธ์น๋ค๊ณ ๋ ๋ณผ ์ ์์ด์. ์ฌ๊ธฐ์ this๊ฐ ์ด๋ป๊ฒ ์ค์ ๋๋์ง ๋ํ ๊ฒฐ์ ๋๋๋ฐ์. ์ด๋ฐ ๊น๋ญ์ this์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ดํดํ๋ ๊ฒ์ JavaScript์์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ฅผ ์ ๋๋ก ํ์ ํ์ง ๋ชปํ๋ฉด ์์์น ๋ชปํ ๋ฒ๊ทธ๋ก ์ด์ด์ง ์ ์์ผ๋ฉฐ, ํนํ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ๋น๋๊ธฐ ์ฝ๋ฐฑ์์ ์์ฃผ ๋ฐ์ํฉ๋๋ค. ๋ฐ๋ผ์, this ๋ฐ์ธ๋ฉ์ ๊ท์น์ ์ดํดํ๊ณ , ํ์ดํ ํจ์์ ๊ฐ์ด this๊ฐ ๋ ์์ปฌ ์ค์ฝํ๋ฅผ ๋ฐ๋ฅด๋ ํจ์๋ฅผ ์ ์ ํ ํ์ฉํ๋ ๊ฒ์ด ์ค์ํด์.
๋ณธ๊ฒฉ์ ์ผ๋ก this์ ๋ํด
์์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ ํจ์์ ํธ์ถ ๋ฐฉ์์
- ์ ์ญ๊ณต๊ฐ์์์ ํธ์ถ
- ํจ์๋ก ํธ์ถ
- ๋ฉ์๋๋ก ํธ์ถ
- ์์ฑ์๋ก ํธ์ถ
- ํจ์์ apply()๋ call()๋ฉ์๋๋ฅผ ํตํด ํธ์ถ ๐ 3. ๋ฉ์๋๋ก ํธ์ถ์์ ๊ฐ์ด ๋ค๋ค์.
- callbackํธ์ถ ๐ ํ์ฌํฌ์คํ ์์ ๋ค๋ฃจ์ง ์๊ณ , ๋ค์ ๋ธ๋ก๊ทธ ํฌ์คํ ์ผ๋ก ์์ธํ๊ฒ ์๊ฐํ ๊ฒ์.
์ด๋ ๊ฒ ์ด๋ฃจ์ด์ ธ ์๋๋ฐ์. ์์ผ๋ก ์์ ์ ํจ๊ป ํ๋์ฉ ์ดํด๋ณผ๊ฒ์.
1. ์ ์ญ ๊ณต๊ฐ ์์์ ํธ์ถ
์ด๋ ๋ฐํ์ ํ๊ฒฝ์ ๋ฐ๋ผ this๊ฐ ๋ฌ๋ผ์ง๋ ๊ฒ์ ๋งํด์ node์ ๊ฒฝ์ฐ global
, browser์ ๊ฒฝ์ฐ window
๊ฐ this๊ฐ ๋์.
2. ํจ์๋ก ํธ์ถ
ํจ์๋ก ํธ์ถ์ด๋ผ๋ ์๋ฏธ๊ฐ ์ฒ์์ ์ ์ ์๋ฟ์ง ์์์ด์. ํจ์๋ก๋ผ๋ ํธ์ถ์ด ํจ์๋ ํจ์๋ก ํธ์ถํ๋๋ฐ ๋ญ๊ฐ ์ด์ํ์ฃ .
์ฑ
์์ ์๊ฒ๋ ์ฌ์ค์ธ๋ฐ, ๋ง์ฝ ๋ฉ์๋๋ ์์ฑ์ ๋๋ apply(), call()์ ํตํด ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ๊ณผ ๊ตฌ๋ณํ๊ธฐ ์ํด ํจ์๋ก ํธ์ถ์ด๋ผ๊ณ ํ๋์. ์ฌํผ ํจ์๋ก์ ํธ์ถ์ ()
๋ฅผ ์ด์ฉํ์ฌ ํธ์ถ ํด์.
์ผ๋ฐ์ ์ผ๋ก ํจ์๋ฅผ ํธ์ถ ํ์๊ณ ํจ์ ๋ด์์ this ๊ฐ ๋๊ตฐ์ง ๋ฌผ์ด๋ณด๋ฉด this๋ ์ ์ญ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
const getThis = ()=>{
return this
}
console.log(getThis()) //๋ธ๋ผ์ฐ์ ์์ ์คํ์ - window, nodeํ๊ฒฝ์์ ์คํ์ - global
์ด ํจ์๋ก์์ ํธ์ถ์ ์ข ์ข ๋ค์์ ์ค๋ช ๋ ๋ฉ์๋๋ก์ ํธ์ถ๊ณผ ๋น๊ต๊ฐ ๋ง์ด ๋๋, ๊ณ์ ์ด์ด๊ฐ๊ฒ์.
3. ๋ฉ์๋๋ก์ ํธ์ถ
this๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํจ์๋ฅผ ์ด๋ป๊ฒ ์ ์ํ๋๋ ๊ด์ฌ๋ณด๋ค๋ ํจ์๋ฅผ ์ด๋ป๊ฒ ํธ์ถ ํ๋๋์ ๊ด์ฌ์ด ๋ ์์ผ๋ฉฐ, ์ด๋ ํจ์๋ก์์ ํธ์ถ์์ ๋น๊ตํ์ฌ ํธ์ถ๋ฐฉ์์ด ์ด๋ป๊ฒ ๋ค๋ฅด๊ณ ์ด์ ๋ฐ๋ผ this๋ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ์ค๋ช ํ ์ ์์ ๊ฒ ๊ฐ์์.
function getThis(){
return this;
}
assert(getThis() === global); // true, ํจ์๋ก์์ ํธ์ถ
const definitionOfThis = getThis;
assert(definitionOfTHIS() === global) // true, ํจ์๋ก์์ ํธ์ถ
const me={
learning : getThis;
}
assert(me.learning() === me) //true,๋ฉ์๋๋ก์์ ํธ์ถ
์์ ์์ ๋ฅผ ํตํด ๋ฉ์๋๋ก์์ ํธ์ถ๊ณผ ํจ์๋ก์์ ํธ์ถ์ ์ฝ๊ฒ ๊ตฌ๋ณํ ์ ์์ด์. ๊ฐ์ฒด ๋ด์ ํ๋กํผํฐ .
์ ์ด์ฉํด ํธ์ถํ ํจ์๋ ๋ฉ์๋๋ก์์ ํธ์ถ๋ก this๋ ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค๊ณ ๋ณผ ์ ์์ฃ .
์ด ์์ ์์ ์ง์ง ๋งํ๊ณ ์ ํ๋๊ฑด getThis
ํจ์๊ฐ ์ด๋ป๊ฒ ์ ์ ๋์๋์ง๊ฐ ๊ด์ฌ์ด ์๋๋ผ ์ด๋ป๊ฒ ํธ์ถ ํ๊ณ ์๋๋์ ๋ฐ๋ผ this๊ฐ ๋ฌ๋ผ์ง๋ค๋ ์ ์ด์์.
๊ทธ๋ฐ๋ฐ ํจ์๋ก์์ this๋ ์ ์ญ๊ฐ์ฒด๋ง ๋ณด๊ณ ์๋ค๋๊ฒ ํ๊ณ์ ์ธ๋ฐ์. ๊ทธ๋ผ ๋ค์๊ณผ ๊ฐ์ ์์ ์์ innerMethod2๋ฅผ ํธ์ถ ํ์ ๋ exampleObj
๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ ์ ์์๊น์?
var exampleObj = {
outerFunc: function() {
console.log(this); // 1. this -> exampleObj
var innerMethod1 = function() {
console.log(this); //2. this->window
};
innerMethod1();
var innerMethod2= function() {
console.log(this); //3. this->window
}
innerMethod2();
}
};
exampleObj.outerFunc();
๋ค์๊ณผ ๊ฐ์ ์ธ๊ฐ์ง ์ ๋์ ๋ฐฉ๋ฒ์ ์ด์ฉํ ์ ์์ ๊ฒ ๊ฐ์์.
- ๋ณ์์ this๋ฅผ ํ ๋นํ์ฌ ๊ทธ ๋ณ์๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐฉ๋ฒ
- es6 ์ arrow function ํ์ฉ ๋ฐฉ๋ฒ.
- ๋ช ์์ ์ผ๋ก call, apply ํ์ฉํ์ฌ this์ง์ ํ๋ ๋ฐฉ๋ฒ
1. ๋ณ์์ this๋ฅผ ํ ๋นํ์ฌ ๊ทธ ๋ณ์๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐฉ๋ฒ
exampleObj.outerFunc()
ํจ์ ํธ์ถ์ ์ํด outerFuncํจ์ ๋ด์์๋ this๋ exampleObj๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ ์ ์ ํ์ฉํ์ฌ ๋ณ์์ ํ ๋นํ ํ, ๊ทธ ๋ณ์์ ์ ๊ทผํฉ๋๋ค.
var exampleObj = {
outerFunc: function() {
console.log(this); // 1. this -> exampleObj {outerFunc: ฦ}
var innerMethod1 = function() {
console.log(this); //2. this->window
};
innerMethod1();
var exampleObjThis = this; โ
์ฐธ์กฐ
var innerMethod2= function() {
console.log(exampleObjThis); // exampleObj {outerFunc: ฦ} โ
์ฐํ์ ์ผ๋ก ๋ณ๊ฒฝ
}
innerMethod2();
}
};
exampleObj.outerFunc();
2. es6 ์ arrow function ํ์ฉ ๋ฐฉ๋ฒ. es6 ๋ถํฐ ๋์ ๋ arrow function์ ํจ์๊ฐ ํธ์ถ๋ ๋(=์คํ์ปจํ ์คํธ๊ฐ ์์ฑ, ํ์ฑํ) this binding์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ์์์ค์ฝํ์ this๋ฅผ ์์์ฒ๋ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
var exampleObj = {
outerFunc: function() {
console.log(this); // 1. this -> exampleObj
var innerMethod1 = function() {
console.log(this); //2. this->window
};
innerMethod1();
var innerMethod2=()=> { โ
ํ์ดํ ํจ์ ์ฌ์ฉ
console.log(this); //3. this->window
}
innerMethod2();
}
};
exampleObj.outerFunc();
3. ๋ช ์์ ์ผ๋ก call, apply ํ์ฉํ์ฌ this์ง์ ํ๋ ๋ฐฉ๋ฒ
์ฌ์ค call, apply๋ ํจ์๋ก์์ ํธ์ถ ์ผ ๋ ๋ฟ ์๋๋ผ, ๊ทธ๋ฅ ๋ช ์์ ์ผ๋ก this๋ฅผ ์ง์ ํ๊ณ ์ถ์ ๋ ์ํฉ์ ๊ตฌ์ ๋ฐ์ง ์๊ณ ์ฌ์ฉํฉ๋๋ค.
call๊ณผ apply๋ ๋งค๊ฐ๋ณ์์ ํ์์ด ๋ค๋ฅด๋ฏ๋ก ์ด ๋ถ๋ถ์ ์ ์ํ์ฌ ์ฌ์ฉํฉ๋๋ค.
call
call(thisArg, arg1, arg2, / โฆ, / argN)
- thisArg ์ this๋ก ์ฌ์ฉํ ๊ฐ์ ๋ฃ์ด์ค๋๋ค. ํจ์๊ฐ ์๊ฒฉ ๋ชจ๋๊ฐ ์๋ ๊ฒฝ์ฐ null ๋ฐ undefined๋ ์ ์ญ ๊ฐ์ฒด๋ก ๋์ฒด๋๊ณ ๊ธฐ๋ณธ ๊ฐ์ ๊ฐ์ฒด๋ก ๋ณํ๋ฉ๋๋ค.
var exampleObj = {
outerFunc: function() {
console.log(this); // 1. this -> exampleObj
var innerMethod1 = function() {
console.log(this); //2. this->window
};
innerMethod1();
var innerMethod2=function(){
console.log(this); //3. this -> exampleObj
}
innerMethod2.call(this); //โ
call method์ฌ์ฉ
}
};
exampleObj.outerFunc();
apply
์์์ ์ ๊น ์ธ๊ธํ์ง๋ง, call๊ณผ apply์ ๋งค๊ฐ๋ณ์ ํ์์ด ์กฐ๊ธ ๋ค๋ฅธ๋ฐ์. thisArg
๋ call๊ณผ ๋์ผํด์. argsArray
๋ ํจ์ ์ธ์๋ค์ array์ ๋ด์์ผ ํจ์ ์๋ฏธํด์.
ํ์ฌ ํฌ์คํ
์์ this๋ฅผ ๋ช
์์ ์ผ๋ก ์ฐ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋ค๋ฃจ๊ณ ์์ผ๋, call๊ณผ apply์ ์ฉ๋ฒ์ ๋ํ ๋ถ๋ถ์ MDN call ํ์ฉ๋ฒ, MDN apply ํ์ฉ๋ฒ์ผ๋ก ๋จ๊ฒจ๋๊ฒ์.
apply(thisArg) apply(thisArg, argsArray)
var exampleObj = {
outerFunc: function() {
console.log(this); // 1. this -> exampleObj
var innerMethod1 = function() {
console.log(this); //2. this->window
};
innerMethod1();
var innerMethod2=function(){
console.log(this); //3. this -> exampleObj
}
innerMethod2.apply(this); //โ
apply method์ฌ์ฉ
}
};
exampleObj.outerFunc();
4. ์์ฑ์๋ก ํธ์ถ
์ฌ๊ธฐ์ ์ผ๋จ ์์ฑ์ ํจ์๊ฐ ๋ฌด์์ธ์ง ์๋ฉด ์ข์๋ฐ์. ์๋ฅผ ๋ค์ด๋ณผ๊ฒ์. ์์ฑ์ ํจ์๋ ๋ง์น ์ฅ๋๊ฐ ๊ณต์ฅ์ ๊ธฐ๊ณ์ฒ๋ผ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ์ญํ ์ ํด์. ์ด ๊ณต์ฅ์ ๊ธฐ๊ณ๊ฐ ์๋ํ ๋๋ง๋ค this๋ ๋ฐ๋ก ๊ทธ ์๊ฐ ๋ง๋ค์ด์ง๋ ์ฅ๋๊ฐ์ ๊ฐ๋ฆฌํค๋ฉฐ, ๊ทธ๋์ ๊ฐ๊ฐ์ ๊ฐ์ฒด๋ this๋ฅผ ํตํด ์๊ธฐ ์์ ์ ์๋ณํ ์ ์์ด์. ์ด๋ ๊ฒ this๋ ์์ฑ์ ํจ์๊ฐ ๋ง๋๋ ๊ฐ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ณํ๋ ๋ฐ ์ฌ์ฉ๋์.
function Toy(name, color) {
this.name = name;
this.color = color;
this.describe = function() {
console.log("This is a " + this.color + " toy named " + this.name + ".");
};
}
var teddyBear = new Toy('Teddy Bear', 'brown');
teddyBear.describe(); // "This is a brown toy named Teddy Bear."
var raceCar = new Toy('Race Car', 'red');
raceCar.describe(); // "This is a red toy named Race Car."
์์ ์์์์ Toy ํจ์๋ ์์ฑ์ ํจ์์ ๋๋ค. new ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ Toy์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ๋, JavaScript ์์ง์ this๋ฅผ ์๋ก ๋ง๋ค์ด์ง ๊ฐ์ฒด, ์ฆ teddyBear์ raceCar์ ๋ฐ์ธ๋ฉํฉ๋๋ค. this.name๊ณผ this.color๋ ๊ฐ๊ฐ์ ์ธ์คํด์ค์ ๋ํ ๊ณ ์ ํ ์์ฑ ๊ฐ์ ์ค์ ํฉ๋๋ค.
teddyBear.describe()๋ raceCar.describe()๋ฅผ ํธ์ถํ๋ฉด, ๊ฐ๊ฐ์ this๋ ํธ์ถ๋ ๋ฉ์๋๊ฐ ์ํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ฏ๋ก, describe ๋ฉ์๋๋ ๊ฐ ๊ฐ์ฒด์ name๊ณผ color ์์ฑ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฐธ์กฐํ์ฌ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
์ ๋ฆฌํ์๋ฉด ์์ฑ์ ํจ์์์ this๋ ์์ฑ์ ํจ์ ํธ์ถ๋ก ์ธํด ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์ ๋ฆฌํ๋ฉฐ
์ด์ ์คํ์ปจํ ์คํธ ํฌ์คํ ์์ lexical scope ๋ฅผ ๋ค๋ฃฐ ๋, ํจ์๊ฐ ์ด๋์ ์ ์ ๋๋์ง๊ฐ ๊ด์ฌ์ฌ์๋ค๋ฉด this์ ๊ฒฝ์ฐ๋ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋๋์ง๊ฐ ๊ด์ฌ์ฌ์ธ ๋ถ๋ถ์ด ๋ค๋ฅด๋ค๊ณ ๋ณผ ์ ์์ด์. ๋ช ์์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ๋ call/apply ๋ ์ข์ง๋ง ๊ฐ์ธ์ ์ผ๋ก es6 ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ชจ๋ ์์ง๋์ด ๋ ๋ฒจ์์ ํต์ฉ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ๋ ํธํ๊ณ , ์ฝ๋๋ ๋ ๊น๋ํ์ง ์์๊น ํด์. ๋ค์ ํฌ์คํ ์์ callback์์ this๋ฅผ ์ข ๋ ๋ค๋ค๋ณผ๊น ํด์.
์ฐธ๊ณ ๋์
- ์กด ๋ ์, ๋ฒ ์ด ๋ฐ์ด๋ณผํธ. (2014). ์๋ฐ์คํฌ๋ฆฝํธ ๋์ ๋น๊ธ Secrets of the JavaScript Ninja.์ธ์ฌ์ดํธ
- ์ ์ฌ๋จ. (2019). ์ฝ์ด ์๋ฐ์คํฌ๋ฆฝํธ.์ํค๋ถ์ค