this의 암시적/명시적 바인딩

DevSheryl·2022년 9월 22일
0
post-thumbnail

책에 따르면 this는 자바스크립트에서 스코프 다음으로 중요한 내용이라고 한다.
볼 때마다 헷갈리는 개념이므로 이번 기회에 예제와 함께 확실히 정리하려 한다.

this의 암시적 바인딩

const myCar = {
	color: 'red',
    logColor: function() {
    	console.log(this.color);
    },
};

myCar.logColor(); // red

이 예제에서 객체의 메서드 내부의 this는 자신이 포함된 메서드를 보유한 객체(myCar)에 자동적으로 바인딩된다.

즉, 메서드(logColor)를 호출하면 this는 자동적으로(암시적으로) myCar가 된다.

this의 명시적 바인딩

위와 달리, 만약 메서드를 바로 호출하지 않고 변수에 담아버린다면(= 한 다리를 건넌다면) 어떻게 될까?

const myCar = {
	color: 'red',
    logColor: function() {
    	console.log(this.color);
    }
}

const unboundGetColor = myCar.logColor; // 호출을 하지 않고 변수에 담기만 했다
// unboundGetColor는 엄밀히 말하면 logColor의 값 부분, 즉 function() { ~ } 부분을 뜻한다.

console.log(unboundGetColor()); // this와 myCar와의 암시적 바인딩이 끊어진 상태이다
// 이때의 this가 포함된 함수는 단독 함수와 동일하다 => this가 window 전역 객체를 가리키게 된다
// window 전역 객체에는 color라는 프로퍼티가 없다 => 결과적으로 undefined 출력

const boundGetColor = unboundGetColor.bind(myCar); 
// this를 '명시적으로'(개발자가 직접) myCar 객체에 바인딩시킴
console.log(boundGetColor()); 
// this가 myCar에 제대로 바인딩되어 myCar 객체의 color 프로퍼티 값(red)을 잘 출력하게 된다.

bind 대신 call이나 apply를 쓸 수도 있다.

bind를 쓸 경우
위의 예제처럼 bind한 내용을 따로 한번 더 실행시켜줘야 하지만
call과 apply는 그럴 필요가 없다.

function Car(maker, color) {
	this.carMaker = maker;
    this.carColor = color;
}

function MyCar(maker, color) {
	Car.call(this, maker, color); // call은 인자를 인수의 나열로 받는다
    this.age = 5;
}

const myNewCar = new MyCar('bmw', 'red');
console.log(myNewCar.carMaker); // bmw
console.log(myNewCar.carColor); // red

call에 MyCar 객체(= this)를 전달하여 Car의 this.carMaker가 MyCar의 인수로 전달한 maker로 설정되도록 했다. (color도 마찬가지)

다음은 같은 내용을 apply로 처리한 코드이다.

...

function MyCar(maker, color) {
	Car.apply(this, [maker, color]); // apply는 인자를 배열로 받는다   
    this.age = 5;
}

...

apply가 call과 비교하여 가지는 장점

apply는 call과 같은 역할(this의 명시적 바인딩)을 한다.
하지만 call보다 분명한 장점이 있다.

바로 함수에 필요한 인수의 수를 모르거나 알 필요가 없을 때도 사용할 수 있다는 것이다.

call은 개별적으로 인수를 전달해야 하므로 이러한 경우 사용할 수 없지만,
apply는 (args 부분을) 배열 형태로 받기 때문에 인수를 몇 개를 받아도 상관 없다.

const ourFunction = function(item, method, args) {
	method.apply(args);
}

ourFunction(item, method, ['argumen1', 'argument2'];
ourFunction(item, method, ['argumen1', 'argument2', 'argument3'];

개인적으로 책에서 언급한 apply의 장점에 가독성도 추가하고 싶다.
인수가 아닌 this가 다른 인수들과 똑같이 나열되어 잘 구분되지 않는 call과 달리,
apply를 사용하면 인수들이 배열로 둘러싸여 있어서 this를 더 명확히 구분할 수 있는 것 같다.

profile
2024 가보자고~!

0개의 댓글