자바스크립트, 화살표함수와 일반함수 차이

2021. 10. 1. 10:51Frontend/JS

 

Medium article 을 읽으면서 일반 함수와 화살표 함수의 차이점에 대해 정리한 글입니다.

1. arguments property

✅  1 - 1. 일반 함수의 arguments

일반함수는 이미 내장된 arguments 라는 프로퍼티가 존재합니다.

어떤 (일반) 함수를 호출할 때 인자로 받은 매개변수를, 함수 내에서 arguments 라는 변수로 호출할 수 있습니다.

 

function func1() {
  console.log(arguments);
  console.log(arguments[3]);
}

func1(1,2,3,4);

>>> Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
>>> 4

✅  1 - 2. 화살표 함수에겐 arguments 프로퍼티가 없다.

대신 화살표 함수는 rest parameter 를 사용하여 arguments 프로퍼티의 효과를 낼 수 있습니다. 아래 코드에는 args 라는 임의의 변수를 사용했습니다.

중요한 것은 `...` spread 연산자로 함수의 매개변수를 그대로 받아와 화살표함수 내부에서 변수로 사용할 수 있게 도와준다.

const arrowFunc = (...args) => {
    console.log(args)
}

arrowFunc(3, 4, 5);

>>> [3, 4, 5]

 

 

✅  1 - 3. arguments 프로퍼티 와 rest parameter 의 차이

arguments 는 배열 객체처럼 보이지만 사실, 매개변수로 전달된 인수(argument) 의 정보를 담고있는 유사 배열 객체(array-like-object)이다. 배열처럼 iterable 한 속성을 가지지만 Array 객체의 메서드를 사용하지 못한다는 차이점이 있다. 아래 코드처럼 arguments 에 forEach() 메서드를 적용하면 에러가 발생한다. 유사 배열 객체는 Array.prototype 의 메서드를 사용하지 못하기 때문이다.

 

 

반면 rest parameter 는 배열객체의 메서드를 온전히 사용할 수 있다.

spread 연산자를 통해 가변 매개변수를 배열로 받을 수 있으며, 이는 실제 배열 객체이기 때문에 배열의 메서드를 그대로 사용할 수 있다. 

 

2. this

✅  화살표 함수의 this

this가 동적으로 결정되는 일반 함수와 달리, 화살표 함수의 this 언제나 상위 스코프의 this를 가리킵니다. (언제나 상위 스코프를 가리키기 때문에 this 에 바인딩 할 객체가 정적 으로 결정된다고 한다.)

 

아래 코드에서 addEventListener 의 콜백함수는 화살표함수로 내부에서 this를 호출합니다.

전역공간에서 선언된 button 식별자의 상위 스코프는 결국 전역(window)이기 때문에 this는 window 를 참조하게 됩니다.

화살표 함수의 this 는 언제나 상위 스코프를 나타낸다는 명제가 들어맞음을 알 수 있습니다.

var button = document.querySelector('#btn')

// 일반함수
button.addEventListener('click', function () {
  console.log(this); //#btn
});


// 화살표함수
button.addEventListener("click", () => {
  console.log(this === window); // => true
  this.innerHTML = "Clicked button";
});

+ 일반 함수는 call, bind, apply 함수를 사용하여 this 를 변경할 수 있지만, 

화살표 함수는 언제나 상위 스코프의 this 만을 가리킵니다. (call, bind, apply ❌)

 

3. constructor 로 사용될 수 없다.

✅ 화살표 함수는 생성자 함수로 사용할 수 없습니다.

생성자 함수는 자신 내부의 prototype 프로퍼티가 가리키는 prototype 객체의 constructor 를 사용하는데, 

화살표함수는 prototype 프로퍼티 자체가 없습니다. 때문에 생성자함수로 사용할 수 없으며, 자신의 인스턴스를 가질 수 없습니다. 

생성자 함수란?
: 동일한 프로퍼티를 가지는 객체를 반복적으로 생성할 수 있는 함수 입니다.

자세한 내용 출처 : https://doitnow-man.tistory.com/132

// 화살표 함수
const Foo = () => {};

Foo.hasOwnProperty("prototype");
>>> false

Foo.hasOwnProperty("arguments");
>>> false

// 일반 함수
function Foo2() {
  return
}

Foo2.hasOwnProperty("prototype");
>>> true

Foo2.hasOwnProperty("arguments");
>>> true

 

4. 같은 이름으로 사용할 없다.

위 특징은 화살표함수를 선언할 때 일반적으로 const (상수) 를 사용하기 때문에, 기존에 동일한 이름으로 선언된 화살표 함수를 재선언 할 수 없게 됩니다.

 

 

정리

일반 함수와 비교하여 화살표 함수는

1. arguments 프로퍼티가 존재하지 않고,

2. 정적으로 this 가 바인딩 되며,

3. constructor (생성자 함수) 로 사용될 수 없습니다.

 

일반 함수와 비교하여 특징이 없다, 안된다의 뉘앙스가 많기 때문에, 화살표 함수를 사용하는 이점이 무엇인지 의아해 할 수도 있습니다.

 

하지만 위 특징을 반대로 생각하면, 

✅  1) arguments 대신 rest parameter 를 사용하면 되고, (일반 함수도 rest parameter 를 사용할 수 있습니다)

✅  2) this 가 어느 스코프에 바인딩 되는지 확실히 파악할 수 있으며, (정적으로 상위 스코프에 바인딩)

✅  3) 생성자 함수로 사용되지 않기 때문에, 함수 자체의 역할에 집중할 수 있습니다.