this 와 this 바인딩

이윤환·2022년 4월 7일
1

js는 흔히들 난해한 언어라고들 한다.
초보들도 쉽게 이해하기 위해 몇 가지 설계를 타 언어들과 조금 다르게 했다는데
그 점이 오히려 난해하게 된 이유라고 한다.(난 그냥 어렵다.)

오늘은 그중에 하나인 this를 정리하겠다.

this

자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다.
그리고 실행 컨텍스트는 함수를 호출할 때 생성된다.
즉 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을 가리키게 된다.

메서드에서의 this

메서드란 객체의 프로퍼티에 할단된 함수로써 그 메서드를 호출 할 때 메서드로써 작동을 한다. 즉 그냥 사용하면 메서드가 아니다.

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 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 메서드다.
이때 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 메서드

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

bind 메서드

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();

정리

  • this는 전역공간에서는 전역 객체를 참조한다
  • 어떤 함수를 메소드로써 호출할 경우 this는 그 메서드의 호출 주체를 참조한다
  • 함수로써 호출 할 경우 this는 전역 객체를 참조한다.
  • 생성자 함수에서의 this는 생성될 인스턴스를 참조한다.
  • call, applly 메서드를 활용하면 this를 명시적으로 지정이 가능하며 함수 또는 메서드를 호출한다.
  • bind 메서드를 활용하면 this 및 함수에 넘길 인자를 일부를 지정한 새로운 함수를 리턴해준다.
profile
나는 이윤환

0개의 댓글