자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다.
그리고 실행 컨텍스트는 함수를 호출할 때 생성된다.
즉 this는 함수를 호출할때 결정된다.
상황에 따라 this가 어떤 값을 보게 되는지 알아보자
간단하다 전역 공간에서 this는 전역 객체를 가리킨다.
브라우저에서는 window Node.js에서는 global이다.
console.log(this); // window, global
console.log(this === window) // true
var a = 1;
console.log(a); // 1
console.log(window.a); // 1
console.log(this.a); // 1
// js에서 모든 변수는 결국 특정 객체의 프로퍼티로써 동작하기 때문에 this.a 가 1을 가리키게 된다.
메서드란 객체의 프로퍼티에 할단된 함수로써 그 메서드를 호출 할 때 메서드로써 작동을 한다. 즉 그냥 사용하면 메서드가 아니다.
let func = function(x){
console.log(this, x);
}
func(1); // window{} 1
let obj = {
method: func
}
obj.method(2) // {method:f} 2
위 코드에서 똑같이 func라는 함수를 호출했으나 결과가 달랐다. 그 차이는 '.'의 유무이다. (혹은 대괄호)
즉 객체의 프로퍼티로 할당된 함수를 사용하는 방식이 메서드이고 그 차이가 this를 달리 바라보게 만드는 원인이다.
구분 자체는 쉽지만 this라는 말 자체가 조금 난해해졌다.
기왕이면 호출 주체가 없더라도 this가 자동으로 주변 환경을 바라봤으면 좋겠다.
다음은 그 방법들이다.
// 상위 스코프의 this를 그대로 활용 가능한 화살표 함수
var obj = {
outer: function(){
console.log(this); // outer
var innerFunc = () => {
console.log(this); // outer
}
innerFunc();
}
}
obj.outer();
call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 메서드다.
이때 call 메서드의 첫 번째 인자를 this로 바인딩 하게 되는데 이를 이용하여 임의의 객체를 this로 지정할 수 있다.
var func = function(a, b, c){
console.log(this, a, b, c);
}
func(1, 2, 3) // window{} 1 2 3
func.call({x: 1}, 4, 5, 6) // {x: 1} 4 5 60
apply 메서드는 call 메서드와 기능적으로 완전히 동일하다.
둘 다 메서드는 첫 번째 인자를 제외 한 나머지 모든 인자들을 호출 할 함수의 매개변수로 지정하나 변수로 일일히 지정하느냐 혹은 배열로 묶어주느냐의 차이다.
var func = function(a, b, c){
console.log(this, a, b, c);
}
func.apply({x: 1}, [4,5,6]); // { x: 1 } 4 5 6
var obj = {
a: 1,
method: function (x, y){
console.log(this.a, x, y);
}
}
obj.method.apply({a: 4}, [5, 6]); // 4 5 6
call과 비슷하나 넘겨 받은 this 및 인수를 바탕으로 새로운 함수를 반환하기만 할 뿐인 함수다. 즉 this를 미리 적용하고 부분 적용 함수를 구현하는 두 가지 목적을 가진 메서드다.
var func = function(a,b,c,d){
console.log(this, a, b, c, debug)
}
func(1,2,3,4); // window{} 1 2 3 4
var bindFunc1 = func.bind({ x:1 });
bindFunc1(5,6,7,8); //{ x: 1} 5 6 7 8
var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
call, apply, bind 메서드 활용
다음은 내부 함수에 상위 컨텍스트의 this를 전달하는 방법이다.
// call
var obj = {
outer: function(){
console.log(this); // outer
var innerFunc = function(){
console.log(this); // outer
};
innerFunc.call(this);
}
}
obj.outer();
// bind
var obj = {
outer: function(){
console.log(this); // outer
var innerFunc = function(){
console.log(this); // outer
}.bind(this);
innerFunc();
}
}
obj.outer();
참고: https://velog.io/@yhlee1227/this-%EC%99%80-this-%EB%B0%94%EC%9D%B8%EB%94%A9