์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ์ฐธ์กฐ๋ณ์(self-reference variable)
์ฆ ๊ฐ์ฒด์งํฅ ์ธ์ด์์ ์๊ธฐ์์ ์ ๊ฐ๋ฆฌํค๋ ๋ณ์์ด๋ค.
๋ฉ์๋๋ ์์ ์ด ์ํ ๊ฐ์ฒด ๋ด์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๊ณ ๋ณ๊ฒฝํ ์ ์์ด์ผ ํจ
โก๏ธ ๋ฉ์๋๊ฐ ์์ ์ด ์ํ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๋ ค๋ฉด ์์ ์ด ์ํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์์ด์ผ ํจ
// object
const circle = {
// property
radius: 5;
// method
getDiameter(){
// ์์ ์ด ์ํ ๊ฐ์ฒด circle๋ฅผ ์ฐธ์กฐํด radius๋ฅผ ์ฌ์ฉ
return circle.radius*2;
}
}
๊ทธ๋ฌ๋ ์ด๋ ๊ฒ ์๊ธฐ ์์ ์ ์ฌ๊ท์ ์ผ๋ก ์ฐธ์กฐํ๋ ๋ฐฉ์์ ๋ฐ๋์งํ์ง ์๋ค
์์ฑ์ ํจ์ ๋ฐฉ์์ผ๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ
function Circle(r){
????.radius = r;
}
Circle.prototype.getDiameter = () => {
return ????.radius * 2;
};
const circle = new Circle(3); // ๋๊ตฌ์ธ์?
???? ์ ์์ ์์ ์์ฑ์ ํจ์๊ฐ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ์ ์ ์๋ค
โก๏ธ ์์ฑ์ ํจ์๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ค๋ฉด ์์ฑ์ ํจ์(= new ํด๋์ค())๊ฐ ์์ด์ผ ํจ
์์ฑ์ ํจ์๋ฅผ ์ ์ํ๋ ์์ ์์ ์์ง ์ธ์คํด์ค๋ฅผ ์์ฐํ์ง ์์
โก๏ธ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ์ ์ ์๋ค.
๋ฐ๋ผ์ ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ํน์ํ ์๋ณ์ this๊ฐ ํ์!
this๋ ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์(self-referencing variable)์ด๋ค
์ฐธ๊ณ ๋ก this๋ ์๋ฌต์ ์ผ๋ก ์์ฑ, ์๋ฌต์ ์ผ๋ก ํจ์ ๋ด๋ถ์ ์ ๋ฌ๋๋ค. ๋ฐ๋ผ์ ํจ์ ๋ด๋ถ์์ ์ง์ญ๋ณ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
(๋จ this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋จ - this binding)
์์ ์ฝ๋๋ฅผ this๋ฅผ ์ฌ์ฉํด ์์ ํ๋ฉด ์๋์ ๊ฐ๋ค
const circle = {
radius: 5;
getDiameter(){
// this: circle
return this.radius * 2;
}
console.log(circle.getDiameter()); // 10
function Circle(r){
// ์ด๋ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค
this.radius = r;
}
Circle.prototype.getDiameter = () => {
// ์ด๋ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค
return this.radius * 2;
};
const circle = new Circle(3);
console.log(circle.getDiameter()); // 6
console.log(this); // window 1. ์ ์ญ์์ this๋ window
function example(num){
console.log(this); // window 2. ์ผ๋ฐ ํจ์ ๋ด๋ถ์์ this๋ window
}
const person = {
name: 'jaman',
getName(){
console.log(this); // 3. ๋ฉ์๋ ๋ด๋ถ์์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด {name:"jaman", getName: function}
return this.name; // jaman
}
};
function Person2(name){
this.name = name;
console.log(this); // 4. ์์ฑ์ ํจ์ ๋ด๋ถ์์ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค Person2 {name: "zaman"}
}
const me = new Person2("zaman");
์๋ฐ์คํฌ๋ฆฝํธ์ this ํจ์๋ ํธ์ถ๋๋ ๋ฐฉ์์ ๋ฐ๋ผ this์ ๋ฐ์ธ๋ฉ ๋ ๊ฐ์ ๊ฐ๋ฆฌํจ๋ค.
์ฆ binding์ด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค!
(๋จ, strict๋ชจ๋์ ๋ฐ๋ผ์ ๋ฐ๋๊ธฐ๋ํจ)
์๋ฐ์คํฌ๋ฆฝํธ์ ํจ์๋ ๊ฐ์ฒด ์ค ์ผ๊ธ๊ฐ์ฒด๋ก ์๋์ ๊ฐ์ ์ผ์ ์ํํ ์ ์๋ค.
1. ๋ณ์๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ
2. ํจ์์ ์ธ์๋ก ์ ๋ฌ
3. ํจ์์ ๋ฐํ๊ฐ์ ์ฌ์ฉ
๋ฐ๋ผ์ ํธ์ถํ๋ ๋ฐฉ๋ฒ๋ ๋ค์ํ๋ฐ
1. ๋จ๋
ํธ์ถ func()
2. ํน์ ๊ฐ์ฒด์ ๋ฉ์๋๋ก ํธ์ถ ๊ฐ์ฒด1.func()
3. ๋์ผํ ํจ์๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ํด ํธ์ถ ๊ฐ์ฒด2.func()
๊ฐ์ ํจ์๋ผ๋ ์ด๋ค ๊ฐ์ฒด์ ์ํด ํธ์ถ๋๋์ง์ ๋ฐ๋ผ this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ๋ฌ๋ผ์ง๋ค(function - this -> some object)
ํจ์๋ฅผ ํธ์ถํ๋ฉด ์คํ ์ปจํ
์คํธ๊ฐ ์์ฑ๋๊ณ ์ด๋ this๋ ํจ๊ป ๊ฒฐ์ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
this์ this๊ฐ ๊ฐ๋ฆฌํฌ ๊ฐ์ฒด๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ โ this binding
๋ฐ์ธ๋ฉ์ ํจ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค this๊ฐ ๋์ ์ผ๋ก ๊ฒฐ์
๊ทธ๋ผ ์ด์ this๊ฐ ํจ์ ํธ์ถ์ ๋ฐ๋ผ ์ด๋ป๊ฒ ์ฐ๊ฒฐ๋๋์ง ์์๋ณด์
1. ์ผ๋ฐ ํจ์ ํธ์ถ โ ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ
2. ๋ฉ์๋ ํธ์ถ โ ์์์ ๋ฐ์ธ๋ฉ
3. ์์ฑ์ ํจ์ ํธ์ถ โ new ๋ฐ์ธ๋ฉ
4. Function.prototype.apply | call | bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ โ ๋ช ์์ ๋ฐ์ธ๋ฉ
: this์ ๊ธฐ๋ณธ ๊ท์น์ผ๋ก ๋๋จธ์ง์ ํด๋น๋์ง ์์ผ๋ฉด ์ด๊ฑฐ
์ผ๋ฐ ํจ์ ํธ์ถ์ this์ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ
'use strict' mode์์ undefined์ ๋ฐ์ธ๋ฉ
โก๏ธ this๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํ ์๊ธฐ ์ฐธ์กฐ ๋ณ์ ๋ฐ๋ผ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๋ ์ผ๋ฐ ํจ์์์ ์๋ฏธ๊ฐ ์๊ธฐ ๋๋ฌธ
function ex(){
console.log("ex's this?", this); // window
function innerEx(){
console.log("innerEX's this?", this); // window
}
innerEx(); // ์ผ๋ฐ ํจ์ ํธ์ถ
}
ex(); // ์ผ๋ฐ ํจ์ ํธ์ถ
cf) ์ค์ฒฉ ํจ์ & ์ฝ๋ฐฑ ํจ์์ ๊ฒฝ์ฐ
: ์ค์ฒฉ ํจ์์ ์ฝ๋ฐฑ ํจ์๋ก ์ผ๋ถ ๋ก์ง์ ๋์ ํ๋ ๊ฒฝ์ฐ, this๋ก ์ ์ญ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋์ด ์๋ก๊ฐ this๊ฐ ์ผ์นํ์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์
โก๏ธ ์ค์ฒฉ์ด๋ ์ฝ๋ฐฑ์์ ์์ ์ด ์ํ ๊ฐ์ฒด์ ๋ฉ์๋์ ์ ๊ทผํ๋ ค๊ณ ํ๋๋ฐ ์ผ๋ฐํจ์๋ก ์ ์ธ๋์ด this๊ฐ ์ ์ญ๊ฐ์ฒด๊ฐ ๋๋ค๋ฉด ์ํ๋ ๋ฉ์๋์ ์์ํ๊ฒ ์ ๊ทผํ๊ธฐ ์ด๋ ค์
// ์ค์ฒฉํจ์
const obj = {
foo() {
function boo() {
console.log(this); // ์ผ๋ฐ ํจ์ ์ ์ธ ๋ฐ๋ผ์ ์ ์ญ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ window
}
boo();
},
};
obj.foo();
// setTimeout callback
const obj = {
foo() {
setTimeout(function () {
console.log(this); // ์ผ๋ฐ ํจ์ ์ ์ธ ๋ฐ๋ผ์ ์ ์ญ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ window
}, 0);
},
};
obj.foo();
๊ทธ๋ผ this๋ฅผ ํต์ผํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
// ๊ฐ๋จํ์ง๋ง ๊ถ์ฅํ์ง ์๋๋ค๊ณ ํ๋ค
// this๋ก ์ฌ์ฉํ๊ณ ์ ํ๋ ๊ฐ์ฒด๋ฅผ ๋ณ์์ ํ ๋นํ์ฌ ์ฌ์ฉ
const example = {
title: "what is this?",
getTitle(){
const self = this; // self๋ฅผ ๋ง๋ค์ด ์ฝ๋ฐฑํจ์์์ ์ฌ์ฉํ ์ ์๋๋ก -> example
setTimeout(function(){
console.log(self.title); // example.title
}, 0);
},
};
example.getTitle(); // what is this?
: ํจ์๋ฅผ ๊ฐ์ฒด์ ๋ฉ์๋๋ก ํธ์ถํ๋ ๊ฒฝ์ฐ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด . ์์ ๊ฐ์ฒด(์ฌ๊ธฐ์๋ inner!)
const outer = {
inner:{
printThis(){
console.log(this); // inner
},
},
};
outer.inner.printThis();
: new ๋ฐ์ธ๋ฉ ์์ฑ์ ํจ์ ํธ์ถ ์์ฑ์ ํจ์๋ ์ด๋ฆ ๊ทธ๋๋ก ๊ฐ์ฒด, ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ํจ์๋ก ์์ฑํ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ
function People(name){
this.name = name; // this๋ me!
}
const me = new Someone('zaman');
: apply, call, bind์ ์ํ ๊ฐ์ ํธ์ถ
์ธ ๋ฉ์๋ ๋ชจ๋ Function.prototype์ ๋ฉ์๋๋ก ๋ชจ๋ ํจ์๊ฐ ์์๋ฐ์ ์ฌ์ฉ ๊ฐ๋ฅ
Function.prototype.apply( thisArg: this๋ก ์ฌ์ฉํ ๊ฐ์ฒด, argsArray: ํจ์์๊ฒ ์ ๋ฌํ ์ธ์ ๋ฆฌ์คํธ์ ๋ฐฐ์ด / ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด)
Function.prototype.call( thisArg: this๋ก ์ฌ์ฉํ ๊ฐ์ฒด, arg1, arg2, ...: ์ ๋ฌํ ์ธ์๋ฆฌ์คํธ๋ฅผ ํ๋ํ๋ ์ ๋ฌ)
Function.prototype.bind( thisArg: this๋ก ์ฌ์ฉํ ๊ฐ์ฒด, arg1, arg2, ...: ์ธ์)
apply, call์ ํจ์๋ฅผ ํธ์ถํ์ง๋ง bind๋ ํจ์๋ฅผ ํธ์ถํ์ง ์๊ธฐ ๋๋ฌธ์ ํธ์ถํด์ฃผ๋ ์์ ์ด ํ์ํ๋ค
๊ท์น์ด ์ค์ฒฉ๋๋ ๊ฒฝ์ฐ๋ฅผ ์ํ ์ฐ์ ์์๋ ๊ฐ๋จํ ์์๋ณด์
๊ธฐ๋ณธ ํจ์๋ก ํธ์ถํ๋ฉด ๊ธฐ๋ณธ + ๋ช
์์ ๋ฐ์ธ๋ฉ
์์ฑ์ ํจ์๋ก ํธ์ถํ๋ฉด new + ๋ช
์์ ๋ฐ์ธ๋ฉ
const example = {
title: "what is this?",
getTitle(){
console.log(this.name)
},
};
// this๋ฅผ example๋ก ์์์ ๋ฐ์ธ๋ฉํด์ค (this.title === "what is this?")
example.getTitle.bind({title:'bind!!!'})();
// bind method๋ฅผ ์ฌ์ฉํด this๋ฅผ {title:'bind!!!'} ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉํด์ค (this.title === "bind!!!")
โก๏ธ ๋ช ์์ ๋ฐ์ธ๋ฉ์ด ์์์ ๋ฐ์ธ๋ฉ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋์
function setTitle(title){
this.name = name;
}
let example = {
title: 'what is this',
};
const setTitleBindExample = setTitle.bind(example); // ๋ช
์์ ๋ฐ์ธ๋ฉ (this.title = 'what is this')
// setTitleํจ์์ example์ ๋ช
์์ ์ผ๋ก ๋ฐ์ธ๋ฉ
example = new TitleBindExample('this is this'); // new ๋ฐ์ธ๋ฉ(this.title = 'this is this')
console.log(example.title); // this is this
โก๏ธ new ๋ฐ์ธ๋ฉ์ด ๋ช ์์ ๋ฐ์ธ๋ฉ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋์
์ฐ์ ์์
new > ๋ช ์์ > ์์์ > ๊ธฐ๋ณธ
ํ์ดํ ํจ์๋ ES6์์ ๋์ ๋ ๋ฌธ๋ฒ์ผ๋ก ์ผ๋ฐ์ ์ธ ํจ์์ ๋ฐ์ธ๋ฉ์์ ์ฐจ์ด๋ฅผ ๋ณด์ธ๋ค.
์์ ๋งํ๋ฏ this๋ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋ ๋ ํจ๊ป ๊ฒฐ์ ๋๋๋ฐ ํ์ดํ ํจ์๋ ์คํ ์ปจํ ์คํธ๋ฅผ ์์ฑํ ๋ this ๋ฐ์ธ๋ฉ์ ํ์ง ์๋๋ค
์ฆ, ํ์ดํ ํจ์ ๋ด๋ถ์ this๋ ์กด์ฌํ์ง ์์
โก๏ธ ๋ฐ๋ผ์ this ํธ์ถ ์ ์์ ์ค์ฝํ์ this์ ์ ๊ทผ (Lexical this)
๋ํ ํ์ดํ ํจ์ ๋ด๋ถ์ this ๋ฐ์ธ๋ฉ์ด ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ช ์์ ๋ฐ์ธ๋ฉ(apply/call/bind)์ ํด์ฃผ๋๋ผ๋ ํ์ดํ ํจ์ ๋ด์์ ์ฌ์ฉํ๋ this๋ ๊ต์ฒด๋์ง ์๋๋ค
const arrow = {
name: 'this in arrow function',
printName: () => {
console.log(this.name);
},
};
arrow.printName(); // ๋ธ๋ผ์ฐ์ ์์ ๋น ๋ฌธ์์ด(window ๊ฐ์ฒด์ name์ด ๋น๋ฌธ์์ด๋ก ์ค์ ๋์ด ์๊ธฐ ๋๋ฌธ), ๋
ธ๋์์ undefined๊ฐ ์ถ๋ ฅ๋จ
์ ์ญ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
โ ๊ฐ์ฅ ๊ฐ๊น์ด ์์ ์ค์ฝํ์ ๊ฐ์ฒด๊ฐ ์ ์ญ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ ES6 ์ถ์ ๋ฉ์๋๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์
const arrow = {
name: 'this in arrow function',
printName(){
console.log(this.name);
},
};
arrow.printName();
class์์ ๊ธฐ๋ณธ์ ์ผ๋ก strict mode๊ฐ ์ ์ฉ!
์์์ ์๊ฒฉ ๋ชจ๋์์ undefined๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค๊ณ ํ์ผ๋๊น
์ผ๋ฐ์ ์ผ๋ก ๋ด๋ถ์์ this ํธ์ถ์ ํด๋์ค๋ก ์์ฑํ ์ธ์คํด์ค ๊ฐ์ฒด๋ก ๋ฐ์ธ๋ฉ
โ ๋ฉ์๋ ๋ด ์ค์ฒฉํจ์๋ ์ฝ๋ฐฑ ํจ์ ๋ฑ์ ์ผ๋ฐ ํจ์๋ก ์ ์ธ, ํธ์ถ ์ this๋ก undefined
: ์์ฑ์ ํจ์๋ฅผ ์ ์ํ๋ ์์ ์์ ์์ง ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์์์ ๋ฐ๋ผ์ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๊ฐ ํ์ โก๏ธ this (self-referencing variable)
ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ฐ์ธ๋ฉ ๋ ๊ฐ์ด ๊ฒฐ์
์ฐธ์กฐ
javascript deep dive
https://www.youtube.com/watch?v=DTX52Pv7PZM