this๋ ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์๋ค. this๋ฅผ ํตํด ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐ ํ ์ ์๋ค.
this๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ํด ์๋ฌต์ ์ผ๋ก ์์ฑ๋๋ฉฐ, ์ฝ๋ ์ด๋์๋ ์ฐธ์กฐํ ์ ์๋ค. ํจ์๋ฅผ ํธ์ถํ๋ฉด arguments ๊ฐ์ฒด์ this๊ฐ ์๋ฌต์ ์ผ๋ก ํจ์ ๋ด๋ถ์ ์ ๋ฌ๋๋ค. ํจ์ ๋ด๋ถ์์ arguments ๊ฐ์ฒด๋ฅผ ์ง์ญ ๋ณ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ฒ๋ผ this๋ ์ง์ญ ๋ณ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค. ๋จ this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ, ์ฆ this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
this๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํ ์๊ธฐ ์ฐธ์กฐ ๋ณ์์ด๋ฏ๋ก ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฒด์ ๋ฉ์๋ ๋ด๋ถ ๋๋ ์์ฑ์ ํจ์ ๋ด๋ถ์์๋ง ์๋ฏธ๊ฐ ์๋ค. ๋ฐ๋ผ์ strict mode๊ฐ ์ ์ฉ๋ ์ผ๋ฐ ํจ์ ๋ด๋ถ์ this์๋ undefined๊ฐ ๋ฐ์ธ๋ฉ๋๋ค. ์ผ๋ฐ ํจ์ ๋ด๋ถ์์ this๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๐ง this ๋ฐ์ธ๋ฉ
๋ฐ์ธ๋ฉ์ด๋ ์๋ณ์์ ๊ฐ์ ์ฐ๊ฒฐํ๋ ๊ณผ์ ์ ์๋ฏธํ๋ค. ์๋ฅผ ๋ค์ด, ๋ณ์ ์ ์ธ์ ๋ณ์ ์ด๋ฆ(์๋ณ์)๊ณผ ํ๋ณด๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฃผ์๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ด๋ค. this ๋ฐ์ธ๋ฉ์ this์ this๊ฐ ๊ฐ๋ฆฌํฌ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉ ํ๋๊ฒ์ด๋ค.
this ๋ฐ์ธ๋ฉ(this์ ๋ฐ์ธ๋ฉ๋ ๊ฐ)์ ํจ์ ํธ์ถ ๋ฐฉ์, ์ฆ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ๋ค. ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ this ๋ฐ์ธ๋ฉ์ด ์ด๋ป๊ฒ ๊ฒฐ์ ๋๋์ง ์์๋ณด์
๐ง ๋ ์์ปฌ ์ค์ฝํ์ this ๋ฐ์ธ๋ฉ์ ๊ฒฐ์ ์๊ธฐ๊ฐ ๋ค๋ฅด๋ค.
ํจ์์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์์ธ ๋ ์์ปฌ ์ค์ฝํ๋ ํจ์ ์ ์๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ์์ ์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ค. ํ์ง๋ง this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ์์ ์ ๊ฒฐ์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค. ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ๋ชจ๋ ํจ์(์ค์ฒฉ ํจ์, ์ฝ๋ฐฑ ํจ์ ํฌํจ) ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
// var ํค์๋๋ก ์ ์ธํ ์ ์ญ ๋ณ์ value๋ ์ ์ญ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ค.
var value = 1;
// const ํค์๋๋ก ์ ์ธํ ์ ์ญ ๋ณ์ value๋ ์ ์ญ ๊ฐ์ฒด์ ํ๋กํผํฐ๊ฐ ์๋๋ค.
// const value = 1;
const obj = {
value: 100,
foo() {
console.log("foo's this: ", this); // {value: 100, foo: ฦ}
console.log("foo's this.value: ", this.value); // 100
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
}
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด ์ค์ฒฉ ํจ์ ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
bar();
}
};
obj.foo();
๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉ ํจ์๋ ์ฝ๋ฐฑ ํจ์์ this ๋ฐ์ธ๋ฉ์ ๋ฉ์๋์ this ๋ฐ์ธ๋ฉ๊ณผ ์ผ์น์ํค๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
// this ๋ฐ์ธ๋ฉ(obj)์ ๋ณ์ that์ ํ ๋นํ๋ค.
const that = this;
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์์ this ๋์ that์ ์ฐธ์กฐํ๋ค.
setTimeout(function () {
console.log(that.value); // 100
}, 100);
}
};
obj.foo();
๋ฉ์๋ ๋ด๋ถ์ this๋ ๋ฉ์๋๋ฅผ ์์ ํ ๊ฐ์ฒด๊ฐ ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
const person = {
name: 'Lee',
getName() {
// ๋ฉ์๋ ๋ด๋ถ์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
return this.name;
}
};
// ๋ฉ์๋ getName์ ํธ์ถํ ๊ฐ์ฒด๋ person์ด๋ค.
console.log(person.getName()); // Lee
const anotherPerson = {
name: 'Kim'
};
// getName ๋ฉ์๋๋ฅผ anotherPerson ๊ฐ์ฒด์ ๋ฉ์๋๋ก ํ ๋น
anotherPerson.getName = person.getName;
// getName ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ anotherPerson์ด๋ค.
console.log(anotherPerson.getName()); // Kim
// getName ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋น
const getName = person.getName;
// getName ๋ฉ์๋๋ฅผ ์ผ๋ฐ ํจ์๋ก ํธ์ถ
console.log(getName()); // ''
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ getName ํจ์ ๋ด๋ถ์ this.name์ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name๊ณผ ๊ฐ๋ค.
// ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name์ ๋ธ๋ผ์ฐ์ ์ฐฝ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋นํธ์ธ ํ๋กํผํฐ์ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ์ ''์ด๋ค.
// Node.js ํ๊ฒฝ์์ this.name์ undefined๋ค.
์์ฑ์ ํจ์ ๋ด๋ถ์ this์๋ ์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
// new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ง ์์ผ๋ฉด ์์ฑ์ ํจ์๋ก ๋์ํ์ง ์๋๋ค. ์ฆ, ์ผ๋ฐ์ ์ธ ํจ์์ ํธ์ถ์ด๋ค.
const circle3 = Circle(15);
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle์๋ ๋ฐํ๋ฌธ์ด ์์ผ๋ฏ๋ก ์๋ฌต์ ์ผ๋ก undefined๋ฅผ ๋ฐํํ๋ค.
console.log(circle3); // undefined
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle ๋ด๋ถ์ this๋ ์ ์ญ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(radius); // 15
apply, call, bind๋ Finctino.prototype์ ๋ฉ์๋์ด๋ฏ๋ก ๋ชจ๋ ํจ์๊ฐ ์์๋ฐ์ ์ฌ์ฉํ ์ ์๋ค.
apply์ call ๋ฉ์๋์ ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ด๋ค. ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ๋ฐฐ์ด/๋ฆฌ์คํธ๋ก ๋ฌถ์ด ์ ๋ฌํ๋ค.
function getThisBinding() {
console.log(arguments);
return this;
}
// this๋ก ์ฌ์ฉํ ๊ฐ์ฒด
const thisArg = { a: 1 };
// getThisBinding ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด๋ฅผ getThisBinding ํจ์์ this์ ๋ฐ์ธ๋ฉํ๋ค.
// apply ๋ฉ์๋๋ ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ๋ฌถ์ด ์ ๋ฌํ๋ค.
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: ฦ, Symbol(Symbol.iterator): ฦ]
// {a: 1}
// call ๋ฉ์๋๋ ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ์ผํ๋ก ๊ตฌ๋ถํ ๋ฆฌ์คํธ ํ์์ผ๋ก ์ ๋ฌํ๋ค.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: ฦ, Symbol(Symbol.iterator): ฦ]
// {a: 1}
function convertArgsToArray() {
console.log(arguments);
// arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํ
// Array.prototype.slice๋ฅผ ์ธ์์์ด ํธ์ถํ๋ฉด ๋ฐฐ์ด์ ๋ณต์ฌ๋ณธ์ ์์ฑํ๋ค.
const arr = Array.prototype.slice.call(arguments);
// const arr = Array.prototype.slice.apply(arguments);
console.log(arr);
return arr;
}
convertArgsToArray(1, 2, 3); // [1, 2, 3]
Functioin.prototype.bind ๋ฉ์๋๋ apply์ call ๋ฉ์๋์ ๋ฌ๋ฆฌ ํจ์๋ฅผ ํธ์ถํ์ง ์๊ณ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ผ๋ก this ๋ฐ์ธ๋ฉ์ด ๊ต์ฒด๋ ํจ์๋ฅผ ์๋กญ๊ฒ ์์ฑํด ๋ฐํํ๋ค.
function getThisBinding() {
return this;
}
// this๋ก ์ฌ์ฉํ ๊ฐ์ฒด
const thisArg = { a: 1 };
// bind ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ thisArg๋ก this ๋ฐ์ธ๋ฉ์ด ๊ต์ฒด๋
// getThisBinding ํจ์๋ฅผ ์๋กญ๊ฒ ์์ฑํด ๋ฐํํ๋ค.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ์ง๋ ์์ผ๋ฏ๋ก ๋ช
์์ ์ผ๋ก ํธ์ถํด์ผ ํ๋ค.
console.log(getThisBinding.bind(thisArg)()); // {a: 1}
bind ๋ฉ์๋๋ ๋ฉ์๋์ this์ ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉ ํจ์ ๋๋ ์ฝ๋ฐฑ ํจ์์ this๊ฐ ๋ถ์ผ์นํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค. ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this๋ฅผ ์ธ๋ถ ํจ์ ๋ด๋ถ์ this์ ์ผ์น์์ผ์ผ ํ๋ค.
const person = {
name: 'Lee',
foo(callback) {
// โ
setTimeout(callback, 100);
}
};
person.foo(function () {
console.log(`Hi! my name is ${this.name}.`); // โก Hi! my name is .
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this.name์ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name๊ณผ ๊ฐ๋ค.
// ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name์ ๋ธ๋ผ์ฐ์ ์ฐฝ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋นํธ์ธ ํ๋กํผํฐ์ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ์ ''์ด๋ค.
// Node.js ํ๊ฒฝ์์ this.name์ undefined๋ค.
});
const person = {
name: 'Lee',
foo(callback) {
// bind ๋ฉ์๋๋ก callback ํจ์ ๋ด๋ถ์ this ๋ฐ์ธ๋ฉ์ ์ ๋ฌ
setTimeout(callback.bind(this), 100);
}
};
person.foo(function () {
console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});
Ref