JavaScript 화살표 함수(arrow function): ES6 이후 함수 선언 방법

화살표 함수(arrow function)

화살표 함수는 ES6 에서 새롭게 도입 된 기존 함수 선언을 간결하게 사용할 수 있게 만드는 새로운 방법입니다. 기존의 함수 표현식 방식으로 변수에 함수 타입의 값을 할당할 때 function 키워드 대신, () => 를 통해 함수를 선언합니다.

const helloPrint = () => {
	console.log('Hello, World!');
};

helloPrint(); // Hello, World! 출력
JavaScript

기존 방식과 화살표 함수의 차이점

기존 방식과 화살표 함수 선언 방식은 다음과 같은 특징이 있습니다.

‘this’ 할당(binding) 동작 차이

JavaScript 에선 this 라는 현재 실행되고 있는 코드의 객체(Object), 범위(Scope)를 가리키는 키워드가 있습니다.

다음 코드는 계산기(calculator) 객체에 생성된 sum 메소드에 다음과 같이 this 를 콘솔에 출력해 보겠습니다.

const calculator = {
    sum: function(a, b) { //더하기 메소드
        console.log(this);
        return a + b;
    },
    difference: function(a, b) { //빼기 메소드
        return a - b;
    },
    product: function(a, b){ //곱하기 메소드
        return a * b;
    },
    quotient: function(a, b){ //나누기 메소드
        return a / b;
    }
}

console.log(calculator.sum(1, 2));
JavaScript

이 코드를 실행하면 다음과 같이 출력 됩니다.

계산기(calculator) 객체 메소드 sum 에서 this 출력예시

그럼 this 에는 sum 메소드가 속한 계산기(calculator) 객체가 할당되어 있습니다.

그런데, 동일한 내용으로 sum 메소드에 생성자 함수가 아닌 화살표 함수로 변경하면 this 출력 시 calculator 객체가 아닌 Window 객체가 출력 됩니다.

const calculator = {
    sum: (a, b) => { //더하기 메소드
        console.log(this);
        return a + b;
    }
}

console.log(calculator.sum(1, 2));
JavaScript
화살표 함수로 this 출력

화살표 함수는 자신만의 this 를 가지지 않습니다. 그 대신 함수가 선언, 생성된 렉시컬 스코프(lexcial scope) 의 this 값을 사용하게 됩니다. 렉시컬 스코프는 이 함수를 사용할 수 있는 범위를 의미 합니다.

그럼 이런 코드를 만들어 볼 수 있겠네요. 지금 함수가 사용되고 있는 렉시컬 스코프 범위 내의 this 를 가져온다고 하니까 객체의 메소드 내에 또 다른 함수를 선언하고 this 를 호출해 보겠습니다.

const calculator = {
    sum: function(a, b) { //더하기 메소드
        const testFn1 = function() {
            console.log(this);
        }
        const testFn2 = () => {
            console.log(this);
        } 
        testFn1();
        testFn2();

        return a + b;
    }
    ...
}

console.log(calculator.sum(1, 2));
JavaScript
메소드 내 함수 선언 후 this 출력 결과

이렇게 출력하고 보니 오히려 화살표 함수 testFn2 는 자신이 동작할 수 있는 렉시컬 스코프에 따라 calculator 객체의 값을 사용하고 있습니다.

그런데 기존 방식으로 생성 된 단독 된 일반 함수 testFn1 내에서 this 는 갑자기 Window 객체를 가리키고 있네요. 이처럼 기존 방식의 함수는 선언 된 범위(scope) 가 아니고 호출 방식에 따라 의도치 않은 결과를 낼 수 있었습니다.

그래서 화살표 함수는 이렇게 개발자가 의도치 않은 동작을 방지하기 위해 명확한 조건으로 동작할 수 있게 개선 되었습니다.

‘arguments(인수)’ 객체 유무

arguments 객체 는 함수에 전달된 인자들의 정보를 지닌 유사 배열 객체를 말합니다. 유사 배열 객체란 의미는 배열과 비슷하게 숫자 인덱스를 지니는 등 사용이 가능한 객체 이지만 배열 그 자체는 아닌 객체를 말합니다.

arguments 객체는 뜻에서도 할 수 있듯, 전달 받은 인수 혹은 인자들을 지니는 객체 입니다. 기존 방식으로 함수 선언 시 내부에 자동으로 arguments 객체가 생성되어 전달 받은 매개변수(parameter) 값을 확인할 수 있었습니다.

function exampleFunction() {
  console.log(arguments.length); // 전달된 인자의 수
  for(let i = 0; i < arguments.length; i++) {
    console.log(arguments[i]); // 각 인자 값
  }
}

exampleFunction(1, 'string', true);
JavaScript
arguments 객체 출력 결과

그런데 화살표 함수에선 이런 arguments 객체가 사라진 이유는 화살표 함수가 기존 방식 보다 간결하고 가독성을 높이기 위한 방향으로 설계 되었기 때문입니다.

그러면 위의 exampleFunction() 처럼 미리 매개변수가 정해져 있지 않고 가변적으로 매개변수를 받아 사용할 수는 없는 걸까요? 그렇지 않습니다. ES6 부터 도입된 rest 매개변수는 기존의 방식과 화살표 함수 모두에서 사용 가능 합니다.

rest 매개변수

rest 매개변수는 …매개변수명 형태로 작성하며 이 매개변수엔 전달된 인수 중 지정 되지 않는 나머지 모든 인수를 배열로 수집하게 됩니다. 유사 배열이 아닌 그냥 배열(Array)로 수집한다는 점도 특징 입니다.

const sum = (...numbers) => {
  let total = 0;
  for (const num of numbers) {
    total += num;
  }
  return total;
};

console.log(sum(1, 2, 3, 4)); // 출력: 10
JavaScript

‘prototype’ 속성 유무

prototype 는 JavaScript 내의 함수 객체가 지니는 속성 입니다. 이 속성은 생성자 함수로 생성된 모든 객체가 메소드와 속성을 공유할 수 있도록 만들어 줍니다.

prototype 속성에 추가, 변경된 내용은 이를 이용해서 생성된 모든 객체가 공유 받게 됩니다. 예를 들어 다음과 같은 코드로 확인해 보겠습니다.

function Car(make, model) {
    this.make = make;
    this.model = model;
}

Car.prototype.drive = function() {
    return this.make + " " + this.model + " is driving.";
};

Car.namePrint = function() {
    return 'name is TESTCar.';
}

const myCar = new Car("Toyota", "Corolla");
console.log(myCar.drive()); // 출력: "Toyota Corolla is driving."
console.log(Car.namePrint()); // 출력: "name is TESTCar."
console.log(myCar.namePrint()); // 출력되지 않음
JavaScript

사용 용도를 아시겠나요? 그런데 화살표 함수는 이 prototype 이 없습니다.

화살표 함수(arrow function)의 단점

최신 문법은 이전 문법의 문제를 해결하기 위해 설계 되지만 무조건 장점만 지니는 것은 아닙니다. 화살표 함수가 지니는 단점은 다음과 같습니다.

자신의 ‘this’ 가 없음

위에서 기존 방식과 차이를 알아볼 때 화살표 함수는 상위 스코프의 this 값을 캡쳐(혹은 사용) 한다는 점을 알았습니다.

이는 this에 부여될 값을 명확하게 예측할 수 있어 장점으로도 볼 수 있지만 객체의 메소드로 사용 되어 객체를 가리키고 싶어도 렉시컬 스코프 범위를 바라보게 되어 단점으로 동작할 수 있습니다.

생성자로 사용할 수 없음

생성자는 new 키워드를 통해 객체를 사용하는 생성자 함수로 사용 할 수 없습니다. 이는 prototype 속성이 없기 때문입니다. 생성자 함수를 호출 할 땐 prototype 속성을 참조하게 되는데 화살표 함수에는 없습니다.

함수에 직접 이름 부여 불가능

화살표 함수는 익명이고 변수에 할당하는 방식으로 우회하여 사용됩니다. 이는 디버깅 시 화살표 함수가 익명 함수로 표시되어 추적이 어려울 수 있다는 단점이 될 수 있습니다.

bind(), call(), apply() 메소드의 사용 제한

화살표 함수는 자신의 this 를 지니지 않는 단점이 여기까지 이어집니다. 이 메소드 들은 this 에 명시적으로 할당(혹은 바인딩) 하기 위해 사용되는 메소드 들인데 this 를 지니지 않으므로 의미가 없어 집니다.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x
목차
위로 스크롤