뭉균의 개발일지

[CS지식] 일반 함수와 화살표 함수의 차이점 본문

CS

[CS지식] 일반 함수와 화살표 함수의 차이점

박뭉균 2024. 10. 3. 15:48

🚪 들어가며  

 

JavaScript에서 화살표 함수는 ES6(ECMAScript 2015)에서 새롭게 도입된 기능입니다. 화살표 함수는 간결한 문법으로 함수 표현식을 작성할 수 있게 해주며, 특히 this 바인딩 방식에서 기존의 일반 함수와 중요한 차이가 있습니다. 이 외에도 다양한 특징들을 일반함수와 비교하여 알아보겠습니다. 해당 포스팅에서 등장하는 예시코드는 JavaScript로 작성했습니다. 

 

 

📌 함수 선언 방식

 

일반 함수: 함수 선언식 또는 함수 표현식으로 정의할 수 있습니다.

function regularFunction() {}  // 함수 선언식

 

화살표 함수: 함수 표현식으로만 사용할 수 있습니다.

const arrowFunction = () => {};  // 함수 표현식

 

여기서 등장하는 함수 선언식과 함수 표현식의 개념도 중요하여 간단하게 정리하고 넘어가겠습니다.

 

 

📝 함수 선언식 (Function Declaration)

 

함수 선언식은 코드에서 명시적으로 이름을 가진 함수를 선언하는 방식입니다. 함수 선언식은 호이스팅(hoisting)이 적용되어, 코드에서 함수 선언이 앞에 있지 않더라도 호출할 수 있습니다.

function 함수이름(매개변수) { // 함수 내용 }

function greet() { console.log("Hello, world!"); } 
greet(); // "Hello, world!" 출력

 

특징

 

1. 호이스팅: 자바스크립트 엔진은 함수 선언을 코드의 최상단으로 끌어올립니다. 즉, 함수정의 전에 호출해도 문제가 없습니다.

2. 명시적인 함수 이름을 가집니다.

3. 함수가 스코프의 최상단에 위치하여 코드 어디에서든 접근 가능합니다.

greet(); // "Hello, world!" 
function greet() { console.log("Hello, world!"); }

 

위의 코드에서 함수가 선언되기 전에 호출되지만, 호이스팅 덕분에 정상적으로 동작합니다.

 

 

📝 함수 표현식 (Function Expression)

 

함수 표현식은 함수를 변수에 할당하는 방식으로 정의됩니다. 함수는 익명 함수로 표현될 수 있으며, 변수에 할당된 시점 이후에만 호출이 가능합니다. 즉, 호이스팅이 적용되지 않습니다.

const 변수명 = function(매개변수) { // 함수 내용 };

const greet = function() { console.log("Hello, world!"); }; 
greet(); // "Hello, world!" 출력

 

특징

 

1. 호이스팅되지 않음: 함수 표현식은 변수에 할당되기 전에는 사용할 수 없습니다.

2. 익명 함수로 사용되거나, 이름을 가진 함수로 할당할 수 있습니다.

3. 할당된 변수를 통해 함수를 호출할 수 있습니다.

console.log(sum(3, 4)); // 에러: sum is not a function 
const sum = function(a, b) { return a + b; };

 

위의 코드에서는 함수 표현식이 변수 sum에 할당되기 전에 호출되므로 에러가 발생합니다.

 

참고로 함수 표현식은 화살표 함수로도 작성할 수 있습니다. 

const greet = () => { console.log("Hello, world!"); }; 
greet(); // "Hello, world!" 출력

 

이렇게 함수 선언식과 표현식의 차이를 알아봤습니다. 다시 본 주제로 돌아가겠습니다. 

 

 

📌 this 바인딩

 

제가 생각하기에는 this 바인딩에서 일반 함수와 화살표 함수의 가장 중요한 차이가 드러나는 것 같습니다.

 

일반 함수: 호출되는 방식에 따라 this가 동적으로 바인딩됩니다. 단독 호출 시 전역 객체가 this로 설정되고 객체 메서드로 호출되면 그 객체가 this가 됩니다.

function regularFunction() { console.log(this); }
regularFunction(); //window

onst obj = {
  value: 10,
  regularFunction: function() {
    console.log(this.value);  
  }
};

obj.regularFunction();  // 10

 

 

화살표 함수: this가 선언될 당시의 상위 스코프에서 바인딩된 값을 사용합니다. 즉, 렉시컬(정적) 바인딩을 따릅니다.

const obj = {
  value: 10,
  arrowFunction: () => {
    console.log(this.value); 
  }
};

obj.arrowFunction();    // undefined (상위 스코프의 this 사용)

 

화살표함수의 상위 스코프는 현재 obj 객체가 아니라 상위스코프인 window 객체이므로 undefined가 출력됩니다.

 

 

📌 생성자 함수

 

일반 함수: 일반 함수는 new 키워드를 사용하면 생성자 함수로 동작합니다. 함수 내부에서 this는 새롭게 생성된 객체를 가리키며, 이를 통해 새로운 객체에 속성이나 메서드를 정의할 수 있습니다.

function RegularFunction() {
  this.value = 10;  // this는 새로운 객체를 가리킴
}

const obj1 = new RegularFunction();  // RegularFunction을 생성자로 사용
console.log(obj1.value);  // 10

 

 

화살표 함수: 화살표 함수는 생성자 함수로 사용할 수 없습니다. 그 이유는 화살표 함수는 일반 함수와 다르게 자신만의 this를 가지지 않기 때문입니다. 화살표 함수에서의 this는 항상 상위 스코프의 this를 가리킵니다. 따라서, new 키워드를 사용하여 객체를 생성하려고 하면 에러가 발생합니다.

const ArrowFunction = () => { this.value = 10; }; 
const obj = new ArrowFunction(); // 에러 발생

 

 

 

📌 arguments 객체

 

일반 함수: 함수 내에서 arguments 객체를 사용하여 전달된 모든 인수를 참조할 수 있습니다.

function regularFunction(a, b) {
  console.log(arguments); // 함수에 전달된 모든 인수를 출력
  console.log(arguments[0]); // 첫 번째 인수 출력
}

regularFunction(1, 2); 
// 출력 결과 
// [1, 2] 
// [1]

 

 

화살표 함수: arguments 객체가 존재하지 않습니다. 대신 상위 스코프의 arguments를 참조합니다.

const arrowFunction = (a, b) => {
  console.log(arguments); // 에러 또는 상위 스코프의 arguments 출력
};

arrowFunction(1, 2); 
// 에러 발생: arguments is not defined
 

 

참고) 상위 스코프에서의 arguments 참조 예시

 

만약 화살표 함수가 상위 스코프에 중첩된 경우, 상위 스코프의 arguments를 참조하게 됩니다. 이를 확인해보겠습니다.

function outerFunction() { 
	console.log(arguments); // [3, 4] 
    const arrowFunction = () => { console.log(arguments); // [3, 4] }; 
    arrowFunction(); 
} 

outerFunction(3, 4);
 

이처럼 화살표 함수는 자신의 arguments 객체를 가지지 않으며, 상위 함수의 arguments를 사용할 수 있습니다.

 

 

💡 결론

 

일반 함수: 호출 방식에 따라 this가 동적으로 결정되고, arguments 객체와 new 키워드를 사용할 수 있습니다.

화살표 함수: this는 상위 스코프에 고정되며, arguments 객체가 없고 생성자 함수로 사용할 수 없습니다.