화살표 함수의 특징과 일반 함수와의 차이점

MochaChoco·2023년 10월 1일
0
post-thumbnail
"지나친 것은 모자란 것과 같다." - 과유불급

여태 화살표 함수를 표기가 간단하단 이유로 일반 함수 표현식 대신 자주 사용했었는데, 특정 상황에서 화살표 함수가 일반 함수와는 다르게 동작한다는 피드백을 받게 되었다.
용도를 알고 적절하게 사용한다면 더 좋은 코드를 작성 할 수 있을 것이라 생각하여, 이번 포스트에서는 화살표 함수에 대해 공부하고 그 내용들을 정리해보기로 한다.

화살표 함수란?

화살표 함수(Arrow function)는 ES6에 도입된 문법으로 전통적인 함수 표현을 좀 더 간단하게 하고자 나온 것이다.

기존 함수 표현식에서 함수를 만들때는 아래와 같이 function 키워드를 사용하여 함수를 만들었다.

// 기존 코드 작성 방식
function sum(a, b) {
  return a + b;
}

// 화살표 함수
const sum = (a, b) => {
  return a + b;
};

// 만일 화살표 함수가 리턴문 한 줄만 가지고 있다면 중괄호({})를 생략할 수 있다.
const sum = (a, b) => a + b;

이처럼 화살표 함수는 function 키워드 대신 => 기호를 사용하여 보다 간단하게 코드를 작성할 수 있다.

1. 화살표 함수의 문법 표현

화살표 함수를 표현할 수 있는 방식은 크게 아래처럼 분류된다.

1) 매개변수 표현

// 매개변수가 없을 경우, 소괄호 생략 불가
() => {
  return true;
};

// 매개변수가 한 개인 경우, 소괄호 생략 가능
x => {
  return x;
};

// 매개변수가 여러 개인 경우, 소괄호 생략 불가
(x, y) => {
  return x + y;
};

2) 함수 몸체 표현

함수 몸체의 코드가 한 줄이고 단순히 return문 밖에 없다면 중괄호({})와 return 키워드를 생략할 수 있다.

x => {
  return x * x;
};

// 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있다.
x => x * x;

3) 객체 리터럴 반환

객체 리터럴이란 아래의 코드처럼 key : value 형식의 data를 직접 입력하는 방법을 말한다.

const person = {
  name : 'Kim'
};

함수 블록의 중괄호와 객체 블록의 중괄호는 형식이 동일하므로 컴파일러가 구분할 수가 없다. 따라서 화살표 함수에서 객체 리터럴을 반환하려면 소괄호(())로 함수 블록을 감싸야 한다.

() => {
  return { name: "Kim" };
};

() => ({ name: "Kim" }); // 함수 몸통을 소괄호로 감싼다.

2. 화살표 함수의 호출 방법

화살표 함수를 호출하기 위해서는 익명 함수로만 호출해야 한다. 여기서 말하는 익명 함수란, 함수명 대신 변수명에 함수 코드를 저장하는 방식을 말한다. 따라서 화살표 함수를 호출하기 위해서는 아래처럼 함수 표현식을 사용한다.

// 일반적인 호출
const pow = x => x * x;
console.log(pow(10)); // 100

// 콜백 함수에 사용할 때
const arr = [1, 2, 3];
const pow = arr.map(x => x * x);
console.log(pow); // [ 1, 4, 9 ]

화살표 함수의 특징

이처럼 화살표 함수는 간결하게 표현할 수 있는 장점이 있지만, 일반적인 함수와는 다른 고유한 특징들 또한 가지고 있다. 따라서 아래의 특징들을 유의하며 화살표 함수를 사용해야 한다.

1. 화살표 함수 내부의 this 키워드는 상위 스코프를 가리킨다.

일반적으로 javascript에서는 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this 키워드에 바인딩할 객체가 동적으로 결정된다. 하지만 화살표 함수 내부의 this는 언제나 상위 스코프의 this를 가리킨다.
그러므로 addEventListener의 콜백 함수로 지정해도 상위 스코프 객체(전역 객체)를 가리키며, apply/call/bind 함수를 통한 this의 바인딩 또한 불가능하다.

※ this 키워드에 관한 내용은 이전 포스트에 정리해놓았으니 참고바랍니다.
var firstName = "Kim";
var lastName = "Jinsu";

let user = {
  firstName: "Park",
  lastName: "Minji",
  showName: function () {
    function showFullName() {
      console.log(this.firstName + " " + this.lastName); // Kim Jinsu
    }

    const showFullName = () => {
      console.log(this.firstName + " " + this.lastName); // Park Minji
    };

    showFullName();
  },
};

user.showName();

위의 예제는 user의 성 + 이름을 호출하는 예제이다.
일반적으로 메소드(객체 멤버 함수) 내부 함수(showFullName 함수)의 this는 전역 객체를 가리키므로 출력값은 "Kim Jinsu"가 된다. 하지만 이것을 화살표 함수로 변경하면 this가 전역 객체가 아니라 상위 스코프의 객체를 가리키게 되므로 user의 성과 이름인 "Park Minji"를 출력하게 된다.

2. 화살표 함수는 arguments 속성을 지원하지 않는다.

arguments란 일반적인 함수가 호출될 때 전달된 파라미터들을 담고 있는 유사 배열 객체를 말한다.

function func() {
  console.log(arguments);
}

func(1, 2, 3); // [1, 2, 3]

일반적인 함수 내부에서 arguments를 콘솔에 출력했을때 파라미터들이 배열 형태로 출력되는 것을 볼 수 있다. 하지만 화살표 함수는 arguments를 지원하지 않기 때문에, 아래의 예제는 같은 동작을 실행하더라도 에러가 출력된다.

const func = () => {
  console.log(arguments);
};

func(1, 2, 3); // Error: arguments is not defined

그 대신 화살표 함수에서 rest parameter(...rest)를 사용하면 파라미터를 일반 함수처럼 배열 형식으로 출력할 수 있다.

// rest parameter를 사용하면 파라미터를 배열 형태로 출력할 수 있다.
const func = (...rest) => {
  console.log(rest);
};

func(1, 2, 3); // [1, 2, 3]

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

생성자 함수란 new 키워드를 통하여 객체를 생성하는 함수를 말한다. 아래의 예제는 이름을 입력받아 Person 객체를 생성하는 예제이다.

function Person(name) {
  this.name = name;
}

const person = new Person("Kim");

console.log(person.name); // Kim

화살표 함수는 생성자로써의 사용이 불가능하며, new 키워드와 함께 화살표 함수를 사용하면 오류가 발생한다.

const Person = (name) => {
  this.name = name;
};

const person = new Person("Kim"); // Error: Person is not a constructor

console.log(person.name);

4. 화살표 함수는 prototype 속성을 지원하지 않는다.

ES6에서 class를 지원하게 되었지만, javascript는 기본적으로 class 기반의 언어가 아니다. 그래서 class의 상속 기능을 따라하고자 javascript에서는 prototype을 도입하게 되었다.

prototype이란?

기본적으로 javascript의 모든 객체는 그들의 부모 객체로부터 property와 method를 상속받는다. 이때 상속되는 정보를 제공하는 객체를 프로토타입(prototype)이라고 한다.

하지만 화살표 함수의 경우, 앞서 말했듯이 객체를 생성할 수 없으므로 prototype 속성 또한 지원하지 않는다.

function Person(name) {
  this.name = name;
}

console.log(Person.prototype); // { constructor: ƒ }

// -------------------------------------------------- //

const Person = (name) => {
  this.name = name;
};

console.log(Person.prototype); // undefined

5. 화살표 함수는 yield 속성을 지원하지 않는다.

yield 키워드란 생성기 함수(function*)를 특정 지점에서 일시 중지하고 next 함수를 사용하여 해당 지점부터 다시 시작하게 만들어주는 키워드이다. 아래는 showNumber 함수를 여러번 호출하여 콘솔에 값을 출력하는 함수이다.

function* showNumber() {
  yield 1;
  yield 2;
  yield 3;
}

let num = showNumber();

console.log(num.next()); // { "value": 1, "done": false }
console.log(num.next()); // { "value": 2, "done": false }
console.log(num.next()); // { "value": 3, "done": false }
console.log(num.next()); // { "value": undefined, "done": true }

하지만 화살표 함수는 생성기 함수 문법 자체를 적용할 수 없으므로 yield 키워드 또한 사용이 불가능하다.

// 올바르지 않은 문법
const showNumber = *() => { // Error: Unexpected token '*'
    yield 1;
    yield 2;
    yield 3;
}

참고 문서

화살표 함수 - Javascript | MDN
Arrow function | PoiemaWeb
유용하지만 위험한 화살표 함수
자바스크립트 화살표 함수 사용법 총정리

profile
길고 가늘게

0개의 댓글