๐ this
์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์ self-referencing-variable ์ด๋ค.
this ๋ฅผ ํตํด ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค์ property ๋ method ๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
๋จ, this ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ (this ๋ฐ์ธ๋ฉ) ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
1. ์ผ๋ฐ ํจ์ ํธ์ถ
2. ๋ฉ์๋ ํธ์ถ
3. ์์ฑ์ ํจ์ ํธ์ถ
4. Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ (๊ฐ์ ) ํธ์ถ
๐ ์ผ๋ฐ ํจ์ ํธ์ถ
๊ธฐ๋ณธ์ ์ผ๋ก this ์๋ ์ ์ญ ๊ฐ์ฒด(global object)๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
(์ด๋ ํ ํจ์[์ค์ฒฉ ํจ์, ์ฝ๋ฐฑ ํจ์ ํฌํจ]๋ผ๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด this ์ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.)
strict mode ๊ฐ ์ ์ฉ๋๋ฉด, this ์๋ undefined ๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
console.log(this) // ์ ์ญ ๊ฐ์ฒด window
function foo(){
console.log("foo's this: ", this); // window
function bar(){
console.log("bar's this: ", this); // window
}
bar();
}
foo();
> this ์ ๋ชฉ์ ์์ฒด๊ฐ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ํ ์๊ธฐ ์ฐธ์กฐ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก๋ ๊ฐ์ฒด์ ๋ฉ์๋ ๋ด๋ถ ๋๋ ์์ฑ์ ํจ์ ๋ด๋ถ์์๋ง ์๋ฏธ๊ฐ ์๊ธฐ์ strict mode ์์๋ ์ ์ฉ๋์ง ์๋๋ค !-!
๐ ์ค์ฒฉ ํจ์, ์ผ๋ฐ ํจ์๋ก ํธ์ถํ๊ธฐ
var value = 1;
// var ํค์๋๋ก ์ ์ธํ ์ ์ญ ๋ณ์ value๋ ์ ์ญ ๊ฐ์ฒด์ ํ๋กํผํฐ์ด๋ค.
// 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();
๐ ์ฝ๋ฐฑ ํจ์, ์ผ๋ฐ ํจ์๋ก ํธ์ถํ๊ธฐ
var value = 1;
const obj = {
value: 100,
foo(){
console.log("foo's this: ", this); // {value: 100, foo: โจ}
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this ์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
setTimeout(function(){
console.log("callback's this: ", this); // window
console.log("callback's this.value: ", this.value); // 1
}. 100);
}
};
obj.foo();
> ๊ทธ๋ ์ง๋ง ์ธ๋ถ ํจ์์ธ ๋ฉ์๋์ ์ค์ฒฉ ํจ์/์ฝ๋ฐฑ ํจ์์ this ๊ฐ ์ผ์นํ์ง ์๋๋ค๋ ๊ฒ์
์ค์ฒฉ ํจ์/์ฝ๋ฐฑ ํจ์๊ฐ ํฌํผ ํจ์๋ก ๋์ํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ ๋ค.
> ๊ทธ๋์ ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉ ํจ์/์ฝ๋ฐฑ ํจ์์ this ๋ฐ์ธ๋ฉ๊ณผ ๋ฉ์๋์ this ๋ฐ์ธ๋ฉ์ ์ผ์น์ํค๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ค.
• 1. ๋ณ์ ํ ๋น
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();
• 2. apply, call, bind ๋ฉ์๋ ์ฌ์ฉํด ์ง์ ๋ฐ์ธ๋ฉ
var value = 1;
const obj = {
value: 100,
foo(){
// ์ฝ๋ฐฑ ํจ์์ ๋ช
์์ ์ผ๋ก this๋ฅผ ๋ฐ์ธ๋ฉํ๋ค.
setTimeout(function(){
console.log(this.value); // 100
}.bind(this),100);
}
};
obj.foo();
• 3. ํ์ดํ ํจ์ ์ฌ์ฉ
var value = 1;
const obj = {
value: 100,
foo(){
// ํ์ดํ ํจ์ ๋ด๋ถ์ this๋ ์์ ์ค์ฝํ์ this๋ฅผ ๊ฐ๋ฆฌํจ๋ค โโ
setTimeout(() => console.log(this.value), 100); // 100
}
};
obj.foo();
๐ ๋ฉ์๋ ํธ์ถ
๋ฉ์๋ ๋ด๋ถ์ this ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
โป ๋ฉ์๋ ๋ด๋ถ์ this ๋ ๋ฉ์๋๋ฅผ ์์ ํ ๊ฐ์ฒด๊ฐ ์๋โ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
};
const me = new Person('Lee');
// getName ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ me๋ค.
console.log(me.getName()); // Lee
Person.prototype.name = 'Kim';
// getName ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ Person.prototype์ด๋ค.
console.log(Person.prototype.getName()); // Kim
// ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name ์ ๋ธ๋ผ์ฐ์ ์ฐฝ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋นํธ์ธ ํ๋กํผํฐ์ด๊ณ , ๊ธฐ๋ณธ๊ฐ์ ''์ด๋ค.
// Node.js ํ๊ฒฝ์์ window.name ์ undefined ์ด๋ค.
๐ ์์ฑ์ ํจ์ ํธ์ถ
function Circle(){
// ์์ฑ์ ํจ์ ๋ด๋ถ์ this ๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
this.radius = radius;
this.getDiameter = function(){
return 2 * this.radius;
};
}
// ๋ฐ์ง๋ฆ์ด 5์ธ Circle ๊ฐ์ฒด๋ฅผ ์์ฑ
const circle_5 = new Circle(5);
// ๋ฐ์ง๋ฆ์ด 10์ธ Circle ๊ฐ์ฒด๋ฅผ ์์ฑ
const circle_10 = new Circle(10);
console.log(circle_5.getDiameter());
console.log(circle_10.getDiameter());
๐ Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ (๊ฐ์ ) ํธ์ถ
apply, call, bind ๋ฉ์๋๋ Function.prototype ์ ๋ฉ์๋์ด๋ค.
apply, call ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ํน์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ ํจ์์ this ์ ๋ฐ์ธ๋ฉํ๋ค.
bind ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ์ง ์๊ณ this ๋ก ์ฌ์ฉํ ๊ฐ์ฒด๋ง ์ ๋ฌํ๋ค.
(๊ทธ๋์ bind ๋ฉ์๋๋ก apply, call ๋ฉ์๋์ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ด๋ ค๋ฉด ๋ช ์์ ์ผ๋ก ํธ์ถํด์ค์ผํ๋ค.)
function getThisBinding(){
console.log(arguments);
return this;
}
const thisArg = {a: 1}; // 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 getThisBinding(){
return this;
}
// this ๋ก ์ฌ์ฉํ ๊ฐ์ฒด
const thisArg = {a: 1};
// bind ๋ฉ์๋๋ ํจ์์ this๋ก ์ฌ์ฉํ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.
// bind ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ์ง๋ ์๋๋ค. ๊ทธ๋์ ๋ช
์์ ์ผ๋ก ํธ์ถํด์ค์ผํ๋ค !
console.log(getThisBinding.bind(thisArg)); // getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a: 1}
๐Lexical Scope ์ this ๋ฐ์ธ๋ฉ
Lexical Scope ๋ ํจ์ ์ ์๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ์์ ์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ค.
this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ์์ ์ ๊ฒฐ์ ๋๋ค.
๐ ์ ๋ฆฌ
ํจ์ ํธ์ถ ๋ฐฉ์ | this ๋ฐ์ธ๋ฉ |
์ผ๋ฐ ํจ์ ํธ์ถ | ์ ์ญ ๊ฐ์ฒด |
๋ฉ์๋ ํธ์ถ | ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด |
์์ฑ์ ํจ์ ํธ์ถ | ์์ฑ์ ํจ์๊ฐ ๋ฏธ๋์ ์์ฑํ ์ธ์คํด์ค |
Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ | Function.prototype.apply/call/bind ๋ฉ์๋์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด |
• ์ฐธ๊ณ ์๋ฃ
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ DEEP DIVE - ์ด์ ๋ชจ
'Front-end > JS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ปค๋ง Currying ๊ณผ ํด๋ก์ (0) | 2022.04.11 |
---|---|
์๋ฐ์คํฌ๋ฆฝํธ ํ๋กํ ํ์ Prototype (2) (0) | 2022.04.04 |
์๋ฐ์คํฌ๋ฆฝํธ ํ๋กํ ํ์ Prototype (1) (0) | 2022.03.09 |
22.02.17 ๋ฉด์ Q & A (0) | 2022.02.18 |
์๋ฐ์คํฌ๋ฆฝํธ๊ฐ data ๋ฅผ ์ ์ฅํ๋ ๋ฐฉ๋ฒ (๋ฉ๋ชจ๋ฆฌ ์ ์ฅ ๋ฐฉ์) (0) | 2022.02.15 |
๋๊ธ