1. this란 무엇일까
this는 자바에서 흔히 쓰이는 this보다 더 확장된 의미로
동적 바인딩되기 때문에 경우마다 다르게 해석된다.
우선 this를 이해하기 전에 실행컨텍스트부터 잘 이해해보자.
https://yulfsong.tistory.com/87?category=797547
전차수를 다시 복기해보면 함수 코드덩어리인 실행컨텍스트가 활성화되는 시점은
"호이스팅이 일어나고, 함수가 실행될 때 열리며, this 바인딩 될때"이다.
그게 this랑 무슨 상관이냐면, 실행컨텍스트라는 맥락을 알아야
우리는 this가 뭘 가리키는 지를 알수가 있다는 것이다.
this는 해당 컨텍스트의 함수가 호출될 때 생성된다.
쉽게 말해, this는 고정된 게 아니라 함수가 호출될 때가 되어서야 해석이 된다.
2. 그 이론을 눈으로 확인하고 외우자
2-1. this의 5가지 경우
(1) 전역 공간에서 : window / global (전역 객체)
(2) 함수 호출에서 : window / global (전역 객체)
(3) 메서드 호출에서 : 메소드 호출 주체 (메소드명 앞)
(4) callback 함수에서 : 기본적으로는 함수내부에서와 동일
(5) 생성자함수에서 : 인스턴스
(1) 전역 공간에서
대표적으로 console.log(this); 라고 하면
우주같은 자바스크립트의 전체를 가리키니까 여기서의 this는 window 객체이다.
(2) 함수 호출에서
function a() {
console.log(this);
}
a();
왠지 여기서의 this는 함수 a일 것만 같은데 틀렸다.
이상하게도 여기서는 window 객체를 가리킨다.
a()는 전역공간에서 호출당했을 뿐이기 때문이다.(그냥 외우자..)
function b() {
function c() {
console.log(this);
}
c();
}
b();
이건 b안에서 c를 호출한거니까
this는 당연히 b()겠지? 하지만 여기서도 window 객체를 가리킨다.
이건 버그인지 특성인지 분분해서 그냥 외우는게 낫다...
var d = {
e: function() {
function f() {
console.log(this);
}
f();
}
}
d.e();
전에 메서드로 소환할 때 메서드 이전까지가 this의 범위랬지.
아하, d.e로 소환했으니까 this가 가리키는 건 e겠네! 땡이다.
정답은 window객체이다.....
메서드로 소환했지만 메서드 안에 함수 f가 있으니까
f()만 보면 된다. this를 직접 소환한 건 함수 f()이다.
호출한 형태만 보면 된다.
결론: 그냥 함수 호출은 몽땅 window라고 외워버리자.
(3) 메서드 호출에서
var d = {
e: function() {
console.log(this);
}
}
d.e();
진짜 메서드 호출이다.
전에 쩜이 붙으면 다 메서드라고 했던 지난 날을 복기해보자.
그리고 쩜 이전까지가 this의 범위라고 했던 것도 함께 기억해보자.
그렇다면 this가 가리키는 것은 d이다.
d는 e를 할당한 변수니까 콘솔 결과는 {e : function}이다.
var a = {
b:{
c: function() {
console.log(this);
}
}
}
a.b.c();
그렇다면 여기서 this는 무엇을 가리킬까.
쩜 이전까지의 범위니까 a.b이고
b는 함수 c를 할당한 메서드니까
결과는 {c: function}이다.
<실무에서 자주 쓰이는 우회법 배우기>
var a = 10;
var obj = {
a: 20,
b: function() {
console.log(this.a); //1
function c() {
console.log(this.a); //2
}
c();
}
}
obj.b();
이 코드는 메서드의 this와 함수의 this가 섞여있다.
1의 this.a는 메서드 호출이니까 obj를 가리키고, obj.a는 20이니까 답은 20이다.
2의 this.a는 함수 호출이니까 전역객체를 가리킬것이고, var a= 10을 받아 답은 10이다.
어떻게 보면 고작 메서드/함수호출로 값이 달라지다니 정말 이상한 부분인 것이다.
둘다 20이라고 생각하기가 편하기 때문에 문제가 생길 수도 있어서
이런 부분은 실무에서 상당히 중요하다..
var a = 10;
var obj = {
a: 20,
b: function() {
var self = this;
console.log(this.a); //1
function c() {
console.log(self.a); //2
}
c();
}
}
obj.b();
추가된 코드는 var self= this; 와 self.a이다.
상사의 코드에서 왜 저런 부분이 들어가나
이유를 몰랐는데 이제 잘 이해가 되었다.
어려울 것 없이 그냥 this를 다른 변수인 self에 담아서 쓰면 둘다 20이 나온다.
(4) callback 함수에서
"기본적으로는 함수에서와 동일"하다는 부분을 생각해보자.
즉, 콜백함수도 '함수'니까 기본적으로 window객체를 가리키긴 하는데,
아닌 경우가 있다는 뜻이다.
var callback = function() {
console.dir(this);
}
var obj = {
a:1,
b: function( cb ) {
cb();
}
}
obj.b(callback);
기본적으로 함수에서와 동일한 경우를 보자.
너무 너무 중요한데 이해가 어려울 수도 있으니 차근차근 잘 따라와보자.
이 콜백함수에서 this는 무엇일까? 순서를 보자.
(1) obj.b 메서드가 실행, callback이라는 메서드가 매개변수로 들어간다.
(2) 여기서 callback이 호출된 건 메서드로서의 호출이므로,
console.dir(this)는 obj.b에서 쩜 이전인 obj를 가리킨다.
(3) 그런데 callback 메서드를 매개변수로 obj.b로 이동한다.
(4) obj.b의 cd로 이 메서드가 들어가는데 cd()라는 함수로 실행이 된다.
(5) cd()로 실행되었다는건 곧 함수로 실행되었다는 것이니까 여기서는 this가 전역객체이다.
결국, 실질적으로 마지막에 실행되는 cd()만 보면 끝인것이다.
함수와 동일하지 않은 경우 = call / apply / bind 메서드를 사용하는 경우
우선 세 메서드를 이해하는 것이 필요하다.
https://yulfsong.tistory.com/90
var callback = function() {
console.dir(this);
}
var obj = {
a:1
b: function( cb ) {
cb.call(this);
}
}
obj.b(callback);
이번에는 cb()가 아니라 cb.call(this)를 사용하였다.
즉, call의 인자인 this로서 var callback이라는 메서드를 명시하여 넣은 것이다.
그러면 메서드로서의 실행이므로 obj가 this이다.
(이 부분은 코드 추가해서 추후 자세히 올릴 예정)
(5) 생성자함수에서
우리가 자바에서 쓰는 this와 같게, 인스턴스를 가리킨다.
function person(name, age) {
this.name = name;
this.age = age;
}
var a = new person('김율프', 5) {
console.log(a);
}
각각 '김율프'와 5를 매개변수로 받은 name, age는
자기자신 this.name, this.age를 가리킨다.
3. 이글의 핵심
다른 부분은 몇 번 보면 이해가 갈 텐데
콜백함수에서의 this는, 특히 this를 직접 바인딩하는 메서드의 경우
헷갈리는 부분이기 때문에 반복해서 봐야한다.
- 정재남님의 자바스크립트 핵심 개념강의를 이해후 재정리한 것
'프로그래밍 > JavaScript' 카테고리의 다른 글
자바스크립트 핵심 개념 : 클로저 (0) | 2020.12.20 |
---|---|
자바스크립트 핵심 개념 : 함수와 변수 사용 (0) | 2020.12.20 |
자바스크립트 핵심 개념 : call / apply / bind 메서드 이해하기 (0) | 2020.12.18 |
자바스크립트 핵심 개념 : 콜백 함수 (0) | 2020.12.18 |
자바스크립트 핵심 개념 : 메서드 (0) | 2020.12.18 |