생성자 메서드에서 일반 함수를 사용하는 것과 화살표 함수를 사용하는 것에는 어떤 차이가 있을까? 예제를 통해 알아보자.
아래 생성자 내부에는 일반 함수 메서드와 화살표 함수 메서드가 있다.
const Fruits = function(fruit) {
this.fruit = fruit;
this.sayFruit1 = function() { console.log(this.fruit); };
this.sayFruit2 = () => { console.log(this.fruit); };
};
// 인스턴스 생성
const apple = new Fruits('Apple');
const grape = new Fruits('Grape');
apple 인스턴스의 메서드를 실행하면 아래와 같이 출력될 것이다.
apple.sayFruit1(); // Apple
apple.sayFruit2(); // Apple
그렇다면 apply
, call
, bind
메서드를 사용해 grape 객체를 apple의 this로 바인딩하면 어떻게 될까?
// apply 메서드로 apple의 this를 grape로 바인딩 시도
apple.sayFruit1.apply(grape); // Grape
apple.sayFruit2.apply(grape); // Apple (변경X)
// call 메서드로 apple의 this를 grape로 바인딩 시도
apple.sayFruit1.call(grape); // Grape
apple.sayFruit2.call(grape); // Apple (변경X)
// bind 메서드로 apple의 this를 grape로 바인딩 시도
apple.sayFruit1.bind(grape)(); // Grape
apple.sayFruit2.bind(grape)(); // Apple (변경X)
화살표 함수인 sayFruit2
는 처음 인스턴스 생성 단계에서 설정된 this 값이 변하지 않는다.
그렇다면 새 변수에 두 메서드를 담아 실행해보자.
const newSayFruit1 = apple.sayFruit1;
newSayFruit1(); // undefined
const newSayFruit2 = apple.sayFruit2;
newSayFruit2(); // Apple
newSayFruit1
은 왜 undefined
가 출력될까?
생성자 내부의 this
는 생성자가 생성하는 객체로 바인딩 된다. 그런데 newSayFruit1
, newSayFruit2
는 객체를 생성하는 인스턴스가 아니다. 그냥 일반 함수다. 일반 함수의 this는 window를 가리키므로 this.fruit
에 대한 값이 없다. 따라서 undefined
가 출력되는 것이다.
하지만 화살표 함수는 코드가 실행되기 위해 필요한 정보(Context)가 처음과 동일하게 유지되기 때문에 Apple
이 출력된다.
일반 함수 형태로 생성자의 메서드를 생성할 경우 this
값이 변할 수 있기 때문에 화살표 함수를 사용하는 게 안전하다.
화살표 함수를 사용하면 this
값이 동일하게 유지되며 this
를 따로 바인딩할 필요도 없다.