자바스크립트를 공부하다보면 필연적으로 this
라는 키워드를 마주치게된다.
하지만 this
가 무엇을 뜻하는지 파악하기 아리송송할때가 있다.
왜 그런걸까?
자바스크립트를 배우기 이전에 C++과 JAVA를 먼저 배웠다면, 더 헷갈리기 쉽다.
왜냐하면 이때의 this
는 클래스를 사용하여 새로 생성된 객체 자기자신을 가르킨다고 암기했기 때문이다.
따라서 C++과 JAVA에서의 this
는 정적인 성격을 띄고있다.
하지만 자바스크립트에서의 this
는 다르다.
자바스크립트의 this
는 동적인 성격을 갖고있다.
동적이라는 말은 함수의 호출시점에서 this
가 결정되므로 값이 고정되어 있지 않다는 뜻이다.
this
를 쉽게 이해하기 위해선 기존에 배웠던 this
는 잠시 제쳐두고 자바스크립트 특유의 유연한 사고방식으로 접근할 필요가 있다.
this
의 관한 여러 포스트들을 읽고 여러 실험을 거쳤을때 가장 쉽게 this를 이해할 수 있는 결론은 이렇다.
this는 함수를 소유한 객체를 가르킨다.
말로 하는것보다 코드를 통해 확인하는것이 더욱 이해가 잘될것이다.
function Person(name,age){
this.name = name
this.age = age
console.log(this)
}
Person('jary',100)
해당 코드를 실행해보면 this
가 나타내는 값이 window
라는것을 확인할 수 있을것이다.
엥?? 갑자기 웬 window
? Person
함수와 window
가 무슨 관계가 있다는거지? 싶을수도있다.
결론적으로 Person
은 window
객체에 포함되어 있다.
왜냐하면 브라우저 환경에서 전역은 window
객체를 뜻하기 때문이다.
따라서 전역 변수, 전역 함수, 전역 객체 모두 window
가 이를 소유하게된다.
위 상황에서 Person
은 전역 함수이기 때문에 window
객체가 이를 소유하게된다.
(window.
가 생략되었다고 볼 수 있다.)
다음 코드를 실행해서 다시 한번 확인해보자.
var name = 'jary' // 전역변수 선언 및 정의
console.log(name) // jary
console.log(window.name) // jary
같은 값을 출력한다.
자, 그러면 this
가 함수를 소유한 객체를 가르킨다고 했으니, Person
함수의 소유권을 변경하고 다시 테스트해보자.
var language = '아직 없음' // 전역 변수이므로 window.language로 접근이 가능하다.
function Person(){
console.log('제가 사용하는 언어는 ' + this.language + '입니다')
}
var Korea = {
language:'한국어'
}
Korea.person = Person
console.log(Person()) // 제가 사용하는 언어는 아직 없음입니다.
console.log(Korea.person()) // 제가 사용하는 언어는 한국어입니다.
var America = {
language:'영어'
}
America.person = Person
console.log(America.person()) // 제가 사용하는 언어는 영어입니다.
America.person = Korea.person
console.log(America.person()) // 제가 사용하는 언어는 영어입니다.
첫번째 출력에서의 Person함수를 소유한 객체가 window
이다. 따라서 this
는 window
를 가르키기 때문에 language
의 값이 아직없음이 출력되었다.
두번째 출력에서는 Person함수를 Korea객체의 person에 할당하도록 하였고 person함수 호출하는 시점에서 함수를 소유하는 객체가 Korea이기 때문에 한국어를 출력한다.
세번째 출력에서는 두번째와 마찬가지로 America객체의 person에 할당하도록 하였고 person함수를 호출하는 시점에서 함수를 소유하는 객체가 America이기 때문에 영어를 출력한다.
네번째 출력에서는 America person에 Korea person함수를 할당했다. 그래도 person함수를 호출하는 시점에서 America객체가 소유하므로 this.language
는 영어를 가르키게 된다.
이해가 되었다면, 다음 예제의 출력을 예측해보자.
function whoAmI(){
console.log(this.name)
}
var a = {
name:"a",
b:{
name:"b",
c:{
name:"c"
}
}
}
console.log(whoAmI())
a.who = whoAmI
console.log(a.who())
a.b.c.who = whoAmI
console.log(a.b.c.who())
a.b.who = a.b.c.who
console.log(a.b.who())
다음에는 bind, apply, call함수를 이용하여 this
를 직접 변경하는 방법에 대해 알아보자.