아직도 코린이지만 정말 배운 지 얼마 안 된 코코코린이 시절에 this를 처음 접했을 땐 당최;; call ? apply? 생성자? 응? 머리에 남는 게 없었다. 그러다 과제를 계속 진행하면서 실제로 this를 사용하고 구체화시키면서 this에 대한 감이 조금은 잡혔으나, 개념적으로 부족한 부분이 있는지 되짚어보고자 오늘은 this에 대해 포스팅을 하려고 한다.
우선 자바스크립트의 경우에는 this가 명확하게 딱 이것이다!로 정의되어 있는 것이 아니다.
사용 패턴에 따라 바인딩 되는 this가 다르다는 것을 알고있어야 한다.
Execution Context
자바스크립트 내에서 함수를 실행 시 execution context 마다 this가 생성된다.
이때의 this는 함수를 실행 할 때 호출 방법에 따라 바인딩되는 this 가 정해진다.
this 바인딩의 5가지 패턴
- Global : window
- Function : window
- Method 호출 : 부모 object
- Construction mode (new 연산자로 생성된 function 영역의 this) : 새로 생성된 객체
- .call / .apply 호출 : call, apply 호출 시 첫번째 인자로 전달된 객체
1. Global : window
초기 글로벌 영역에서의 this는 window 객체 임을 확인할 수 있다.
그럼 전역 영역에 var 키워드를 사용하여 변수를 선언했을 경우 어떻게 될까?
var 키워드는 전역 영역, 즉 글로벌 스코프로 변수를 선언한다. 이경우 변수 a의 this는 window가 된다.
그럼 a면 a이고, this면 그냥 this이지 굳이 왜 this.a 마냥 dot이 붙어있는 건지 바로 와 닿지 않을 수 있다.
위와 같이 window 객체를 다시 한 번 조회해보면 전역 변수 a가 윈도우 객체의 속성으로 명시되어 있는 것을 확인할 수 있다.
window가 객체!!!!라는 것을 안다면 이해하는 데 도움이 될 것 같다.
var a = 'tired';
console.log(this.a) // 'tired';
console.log(this) // Window 객체 ~
2. Function : window
var a = 'tired';
function tempA() {
function tempB() {
function tempC() {
console.log(this) // window 객체
console.log(this.a) // 'tired'
}
tempC();
}
tempB();
}
tempA();
함수 내 내장함수가 아무리 많아도 함수에서의 this는 전역 영역. window 객체임으로 위에서 소개한 global과 동일한 성질이다.
3. Method 호출 : 부모 object
method 호출은 객체.메소드() 와 같이 객체 내에 있는 함수(메소드)를 호출하는 방법이다.
메소드 호출에서의 this는 왼쪽 부모 객체이다.
간단하게 말하자면 메소드 호출 앞에 있는 객체가 this라고 생각하면 된다.
var a = {
val : 0,
increment: function() {
this.val++;
}
}
console.log(a); // {val: 0, increment: ƒ}
a.increment(); // Method 호출, this === a
console.log(a); // {val: 1, increment: ƒ}
위 코드와 같이 메소드 호출 시 앞에 있는 부모 a객체가 this로 바인딩된다.
4. Construction mode (new 연산자로 생성된 function 영역의 this) : 새로 생성된 객체
function People(name) {
this.name = name;
}
//새 인스턴스 만들기
let people = new People('deemmun');
console.log(people.name); // 'deemmun'
console.log(name) // ReferenceError
new 연산자를 이용하여 새 인스턴스를 만드는 과정 중 함수 construtcor People 내 사용된 this는 people 객체가 this로 바인딩된다.
인스턴스 people, 인스턴스에서 this를 참조하고 있는 것이고, 그냥 name을 콘솔에 출력할 경우 전역 영역에 name이 없는 상태이기 때문에 참조 오류가 발생한다.
5. .call / .apply 호출 : call, apply 호출 시 첫번째 인자로 전달된 객체
call, apply 메소드를 호출하는 경우는 this를 명시적으로 지정하고 싶을 때 사용한다.
첫 번째 인자가 this로 지정된다는 점을 유의하면 된다.
call과 apply의 차이점은 전달 인자가 많을 경우 apply의 매개변수가 array의 형태로 들어가게 작성을 한다.
위의 코드에서의 this가 'I Love I-U' 로 지정되며, this에서 string.prototype.split 이 작동된 것이다.