๐ This
์๋ฐ์คํฌ๋ฆฝํธ์์ this๋ "๋์ "์ผ๋ก ์ ํด์ง๋ค๋ผ๊ณ ํ๋ค. ๊ธฐ์กด ๊ฐ์ฒด์งํฅ ์ธ์ด๋ค๊ณผ๋ ๋ค๋ฅด๊ฒ ์๋ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ this์ ๋ํด ์ ๋ฆฌํด ๋ณด๋ ค ํ๋ค.
๐โโ๏ธ This๋
this๋ ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ๋ง๋ค์ด ์ง ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ์์ด๋ค. ์ดํด๋ฅผ ์ํด ๋ค์ ์ฝ๋๋ฅผ ๋ณด์
const square = {
distance: 5,
getArea() {
return square.distance ** 2
},
}
console.log(square.getArea())square ๊ฐ์ฒด์ getArea ๋ฉ์๋๋ distance๋ฅผ ์ด์ฉํด ๋์ด๋ฅผ ๊ณ์ฐํ๋ค. ์ด๋ ์ค์ํ ๊ฒ์ square๊ฐ ๊ฐ์ง๊ณ ์๋ ์์ฑ์ธ distance๊ฐ์ด ํ์ํ๋ค๋ ์ ์ด๋ค. ๊ฐ์ฒด๋ฅผ ์ ์ธํ ๋ณ์ square๋ฅผ ์
๋ ฅํ๋ฉด distance๋ฅผ ์ฌ์ฉํ ์๋ ์์ง๋ง, ํญ์ ๊ฐ์ฒด๋ฅผ ์ ์ธํ ์๋ณ์๋ฅผ ์ด์ฉํ๋ค๋ฉด ์ค์ง square๋ผ๋ ์ด๋ฆ์ ๊ฐ์ฒด์์๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํด ์ฌ์ฌ์ฉ์ฑ์ด ๋จ์ด์ง๊ฒ ๋๋ค.
์ด๋ฌํ ์ฌ์ฌ์ฉ์ฑ์ ๊ณ ๋ คํด ๊ฐ์ฒด๊ฐ ์ด๋ป๊ฒ ์ ์ธ๋๋์ง์ ์๊ด์์ด, ์ด๋ค ์ด๋ฆ์ ์ธ์คํด์ค์ธ์ง ์๊ด์์ด ํญ์ ์๊ธฐ ์์ ์ ์ฐธ์กฐํ ์ ์๋ ๋ณ์๊ฐ ๋ฐ๋ก this๋ผ๊ณ ์ดํดํ ์ ์๋ค.
์๋ฅผ ๊ฐ์ฒด ๋ฆฌํฐ๋ด, ์์ฑ์ํจ์, class๋ก ๋ค์๊ณผ ๊ฐ์ด ํํํ ์ ์๋ค.
const square1 = {
distance: 5,
getArea() {
return this.distance ** 2
},
}
function ProtoSquare(distance) {
this.distance = distance
}
ProtoSquare.prototype.getArea = function () {
return this.distance ** 2
}
const square2 = new ProtoSquare(5)
console.log(square2.getArea())
class ClassSquare {
constructor(distance) {
this.distance = distance
}
getArea() {
return this.distance ** 2
}
}
const square3 = new ClassSquare(5)
console.log(square3.getArea())์ด๋ฌํ this๋ "์ด๋ป๊ฒ" ๊ฒฐ์ ๋๋ ๊ฑธ๊น?
๐ this๊ฐ ๊ฒฐ์ ๋๋ ๋ฐฉ์
this๋ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋๋๋์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋๋ฐ, this ๋ฐ์ธ๋ฉ์๋ 4๊ฐ์ง ๊ท์น์ด ์๋ค. 4๊ฐ์ง ๊ท์น์ ๋ํด ์์๋ณด์.
1) ๊ธฐ๋ณธ๋ฐ์ธ๋ฉ
๊ฐ์ฒด์ ๋ฉ์๋๋ ์์ฑ์ ํจ์๋ฅผ ์ ์ธํ ํจ์๋ค, ์ผ๋ฐํจ์๋ก ํจ์ ๋ด๋ถ์์ this๋ฅผ ํธ์ถํ๋ฉด ์ ์ญ๊ฐ์ฒด๋ฅผ ์ป์ ์ ์๋ค. ์ ์ญ๊ฐ์ฒด๋ ๋ธ๋ผ์ฐ์ ๋ Node.js๋์ ๋ฐ๋ผ ๊ฐ๊ฐ window์ global์ ์๋ฏธํ๋ค. ๋ธ๋ผ์ฐ์ ๊ธฐ์ค์ผ๋ก ์ ์ญ๊ฐ์ฒด๋ window๋ก ์ค๋ช
์ ์งํํ๋ ค ํ๋ค.
function hi() {
console.log(this) //window ๋๋ global
}
hi()์ด๋ ๋ฉ์๋ ๋ด๋ถ ์ค์ฒฉ ํจ์๋ ์ฝ๋ฐฑํจ์๊ฐ ์ผ๋ฐํจ์๋ก ํธ์ถ๋ ๊ฒฝ์ฐ์๋ ๋์ผํ๊ฒ ์ ์ญ ๊ฐ์ฒด๋ก this ๋ฐ์ธ๋ฉ์ด ๋๋ค.
var value = 1
const obj = {
value: 100,
foo() {
setTimeout(function () {
console.log(this) // window
console.log(this.value) // 1
}, 100)
},
too() {
function bar() {
console.log(this) // window
console.log(this.value) // 1
}
bar()
},
}
var value = 1
const obj = {
value: 100,
too() {
"use strict"
function bar() {
console.log(this) // undefined
console.log(this.value) // Uncaught TypeError: Cannot read properties of undefined
}
bar()
},
}
obj.too()์ด๋ use strict๋ก ์๊ฒฉ๋ชจ๋๋ฅผ ์ ์ฉํ๋ฉด ์ ์ญ๊ฐ์ฒด๋ ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ์์ ์ ์ธ๋์ด this.value๋ ์๋ฌ๋ฅผ ๋์ง๊ฒ ๋๋ค.
2) ์์์ ๋ฐ์ธ๋ฉ
ํธ์ถํ ๋์ ๊ฐ์ฒด์ ์กด์ฌ ์ฌ๋ถ์ ๋ฐ๋ผ, this๋ ๋ง๋ค์ด์ง ๊ฐ์ฒด์ ์ํด์ง์ง ์๊ณ , ํธ์ถํ ๊ฐ์ฒด, ์ปจํ
์คํธ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค. ์ด๊ฒ์ ์์์ ๋ฐ์ธ๋ฉ์ด๋ผ ํ๋๋ฐ ์ดํด๋ฅผ ์ํด ๋ค์ ์์ ๋ฅผ ๋ณด์.
const person = {
name: "lee",
getName() {
return this.name
},
}
console.log(person.getName()) //lee
const anotherPerson = {
name: "kim",
}
anotherPerson.getName = person.getName
console.log(anotherPerson.getName()) //kim
const getName = person.getName
console.log(getName()) // window์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด getName์ด ํจ์๊ฐ ์ฌ์ฉ๋๋ ๊ณณ์ ๋ฐ๋ผ this๊ฐ ๋ฌ๋ผ์ง๋ค. ๊ฐ์ฒด์์ ์ ์ธ๋ this๋ผ๋ฉด ํด๋น ๊ฐ์ฒด์ binding์ด ๋์ด์ผ ํ์ง๋ง, ํธ์ถํ๋ ๊ฐ์ฒด๊ฐ ๋๊ตฌ๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํจ์๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ ๋
๋ฆฝ์ ์ธ ์ปจํ
์คํธ ๊ฐ์ฒด๋ผ๊ณ ๋ณผ ์ ์๋ค. ์ด๋ฌํ ๊ฒฐ๊ณผ๋ ํจ์์ ์ปจํ
์คํธ๋ ํจ์๊ฐ ์คํ๋ ๋ ๋ง๋ค์ด์ง๊ณ , ๋ง๋ค์ด์ง๋ ๊ณผ์ ์์ this๊ฐ ๋ฐ์ธ๋ฉ๋๊ธฐ ๋๋ฌธ์ ๊ทธ๋์ ์ปจํ
์คํธ ๊ฐ์ฒด๊ฐ this์ ๋ฐ์ธ๋ฉ๋๋ค.
function foo() {
console.log(this.text)
}
var name = {
text: "์์ค",
foo: foo,
}
var person = {
text: "๊ฐ์",
name: name,
}
person.name.foo()๋ง์ฝ ์ค์ฒฉ๋ ์ํ์์ ํธ์ถํ๊ฒ ๋๋ค๋ฉด ๊ฐ์ฅ ๊ฐ๊น์ด ๊ฐ์ฒด, name์ ์์์ ์ผ๋ก ์ปจํ ์คํธ ๊ฐ์ฒด๋ก ๋ฐ์ธ๋ฉํ๋ค.
์ด๋ ๊ฒ ์ด๋์ ํธ์ถํ๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ฉด ์์ธกํ๊ธฐ ์ด๋ ต๊ณ ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์๋ค. this binding์ ์ฐ๋ฆฌ๊ฐ ์ ํ๋ ๋ฐฉ๋ฒ์ ์์๊น?
3) ๋ช ์์ ๋ฐ์ธ๋ฉ
this binding์ ๋ช ์์ ์ผ๋ก ์ ํด์ฃผ๋ ๋ฐฉ์์๋ apply, call, bind ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
apply์ call
๋ ๊ฐ์ง ๋ฉ์๋๋ ์ฌ์ฉ ์ ์ ๋ฌํ ๊ฐ์ฒด๋ฅผ this์ ๋ฐ์ธ๋ฉํ๊ณ , ํธ์ถํ๋ค. ๋๊ฐ์ง ๋ฉ์๋์ ์ฐจ์ด์ ์ ํจ์์ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์ ์๋ค. apply๋ ๋ฐฐ์ด๋ก ์ธ์๋ฅผ ์ ๋ฌํ๊ณ call์ ํ๋ ํ๋์ฉ ์ ๋ฌํ๊ณ ํธ์ถํ๋ค.
function getThisBinding() {
console.log(arguments)
return this
}
const thisArg = { a: 1 }
console.log(getThisBinding())
console.log(getThisBinding.apply(thisArg, [1, 2, 3])) //[1, 2, 3]
console.log(getThisBinding.call(thisArg, 1, 2, 3)) //[1,2,3]bind
bind๋ this๋ง ๋ฐ์ธ๋ฉํ๊ณ ํธ์ถ์ ํ์ง ์๋๋ค. ์ฝ๋ฐฑํจ์๋ ์ค์ฒฉํจ์๊ฐ ์ผ๋ฐํจ์๋ก ํธ์ถ๋์์ ๋, this๊ฐ ๋ฌ๋ผ์ง๋ ๋ฌธ์ ๋ฅผ ๋ช ์์ ์ผ๋ก ํด๊ฒฐํด ์ค ์ ์๋ค.
const person = {
name: "lee",
foo(callback) {
setTimeout(callback.bind(this), 100)
},
}
person.foo(function () {
console.log(this.name) //lee
})4) new ๋ฐ์ธ๋ฉ
์์ฑ์ํจ์ ๋ด๋ถ์ this๋ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
function foo() {
this.name = "์์ค"
this.callName = function () {
console.log(this.name)
}
}
const bar = {
name: "์ฃผํฌ",
}
const x = new foo()
x.callName.bind(bar)
x.callName() // ์์ค์์ฑ์ ํจ์๋ฅผ ์ด์ฉํด ๋ง๋ x ๊ฐ์ฒด์ ๋ช ์์ ๋ฐ์ธ๋ฉ์ธ bind๋ก bar๋ฅผ ๋ฐ์ธ๋ฉํ๋ คํ์ง๋ง, new ๋ฐ์ธ๋ฉ์ด ์ฐ์ ์์๊ฐ ๋์ "์์ค"์ผ๋ก ๋์จ ๊ฒ์ ๋ณผ ์ ์๋ค.
๐ผ ์์ธ์ ์ธ ๋ฐ์ธ๋ฉ: ํ์ดํ ํจ์
์์ ์ค๋ช ํ this ๋ฐ์ธ๋ฉ๊ณผ๋ ๋ค๋ฅด๊ฒ ์์ฉํ๋ค.ํ์ดํ ํจ์๋ ํจ์ ์์ฒด๊ฐ this๋ฅผ ๊ฐ์ง ์์ ํจ์ ์ ์ธ ์์ ์์ ์ค์ฝํ์ this๋ฅผ ๋ฐ์ธ๋ฉํ๋ค. ํญ์ this๋ฅผ ๋ณด์ฅํ๊ธฐ ๋๋ฌธ์ callbackํจ์์์ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
function foo() {
setTimeout(() => {
console.log(this.name)
}, 1000)
}
const bar = {
name: "์์ค",
}
foo.call(bar) // ์์ค์์ ์์๋ฅผ ๋ณด๋ฉด setTimeOut ์ฝ๋ฐฑํจ์์ this๋ foo์ this๋ฅผ ์ฐธ์กฐํ๋๋ฐ ํ์ฌ call์ ์ด์ฉํด bar๋ก ๋ฐ์ธ๋ฉ๋์ด ๊ฒฐ๊ณผ๊ฐ ์ฒ ์๋ก ๋ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
const foo = {
name: "์์ค",
bar: () => console.log(this.name),
}
foo.bar() // undefined
const boo = {
name: "์์ค",
far() {
console.log(this.name)
},
}
boo.far() //์์คํ์ง๋ง ์ฃผ์ํ ์ ์ ๋ฉ์๋๋ฅผ ํ์ดํํจ์๋ก ๋ง๋ค๊ฒ ๋๋ฉด foo ๊ฐ์ฒด๊ฐ ์๋๋ผ ์์ ์ค์ฝํ์ this์ธ ์ ์ญ๊ฐ์ฒด๋ฅผ bindingํ๊ฒ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฉ์๋๋ ๋ฉ์๋ ์ถ์ฝ์ผ๋ก ์ ์ํ๋ ๊ฒ ๋ซ๋ค๋ ๊ฒ์ ์ ์ ์๋ค. ์ฌ๊ธฐ์ ํท๊ฐ๋ ธ๋ ๊ฒ์ bar๋ผ๋ ๋ฉ์๋๋ฅผ ํจ์ ์ค์ฝํ๋ก ์๊ฐํด์ผ ํ๋์ง ์ฌ๋ถ์๋ค. ๋ฉ์๋๋ ๊ฒฐ๊ตญ ๊ฐ์ฒด์ ํค์ ์ฐ๊ฒฐ๋ ํจ์์ ์ฐธ์กฐ๊ฐ์ด๋ฏ๋ก ์ด๊ฒ ์์ฒด๊ฐ ํจ์ ์ค์ฝํ๋ฅผ ๊ฐ์ง์ง ์์ ์์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋ง์น๋ฉฐ
this ๋ฐ์ธ๋ฉ์ ์์์น ๋ชปํ๋ ์๋ฌ๋ฅผ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ ๊ผญ ํ๋ฒ ์ ๋ฆฌ๋ฅผ ํ๊ณ ๋์ด๊ฐ์ผ ํ๋ค. ์์ง ํ์ดํ ํจ์์์ ๋ง์ง๋ง ๋ถ๋ถ์ด ์ ์ ์ญ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉํ๋์ง ์ ์ดํด๊ฐ ๋์ง ์์ ์์ฑ์ํจ์์ prototype์ ๋ํด์ ์ ๋ฆฌํ๊ณ ๋ค์ํ๋ฒ ํ์ธ์ ํด๋ณด๋ ค๊ณ ํ๋ค.
[์ฐธ๊ณ ]