JavaScript에서 함수를 정의하는 방법에는 크게 두 가지 방법이 있다: 함수 선언식(Function Declaration)과 함수 표현식(Function Expression). 이 두 방식은 각기 특징과 사용 시점에 따라 선택할 수 있다. 함수를 정의하는 여러 가지 방법에 대한 차이와 특징을 알면, 자바스크립트를 좀 더 깊이 있게 이해하고 효율적으로 사용할 수 있다.
함수 선언식은 function
키워드로 시작하며, 이후에 함수의 이름, 매개변수 목록, 그리고 중괄호 {}
로 둘러싸인 함수의 본문이 온다.
예시:
function sum(a, b) {
return a + b;
}
특징
예시:
console.log(sum(1, 2)); // 결과: 3
function sum(a, b) {
return a + b;
}
함수 표현식은 함수를 생성하고 변수에 할당하는 방식으로 정의한다. 이 방식은 function
키워드 다음에 함수 이름이 오지 않고, 바로 매개변수와 함수 본문이 온다. 그리고 이 함수를 변수에 할당한다.
예시:
const sum = function(a, b) {
return a + b;
};
특징
예시:
console.log(sum(1, 2)); // TypeError: sum is not a function
const sum = function(a, b) {
return a + b;
};
호이스팅(Hoisting)의 영향: 함수 선언식은 호이스팅에 영향을 받아서 함수 선언 전에도 호출이 가능하나, 함수 표현식은 변수의 호이스팅만 영향을 받으므로 함수 할당 전에는 호출할 수 없다.
익명성: 함수 표현식은 이름이 선택사항이므로 익명 함수(Anonymous function)로 사용될 수 있다. 하지만 함수 선언식은 반드시 이름을 가져야 한다.
사용 상황: 함수 표현식은 콜백 함수, 즉시 실행 함수(IIFE, Immediately Invoked Function Expression), 클로저(Closure) 등 다양한 고급 패턴에서 주로 사용된다.
자바스크립트에서는 함수 선언과 변수 선언이 그들이 속한 스코프의 최상단으로 끌어올려진 것처럼 동작하는데, 이 현상을 호이스팅이라고 한다. 하지만 실제로 코드가 물리적으로 이동하는 것은 아니다. 대신, 자바스크립트 엔진이 코드를 해석할 때 선언부를 최상단으로 인식하게 하는 특성을 말한다.
예시:
console.log(a); // undefined
const a = 5;
console.log(a); // 5
위 코드에서 var a = 5;
선언 전에 console.log(a);
를 실행했음에도 불구하고 에러가 발생하지 않는다. 이는 var a;
선언 부분이 호이스팅되어 스크립트의 최상단에서 실행된 것처럼 동작하기 때문이다.
함수 선언식과 함수 표현식은 각각의 특징과 사용 시점에 따라 적절하게 선택하여 사용할 수 있다. 호이스팅의 개념을 잘 이해하고, 이를 통해 어떤 방식의 함수 정의 방식을 선택할지 판단하는 능력은 자바스크립트를 효과적으로 사용하는 데 중요하다.
함수 표현식의 유용성은 다양한 고급 패턴에서 더욱 잘 드러난다. 이번 섹션에서는 그 중 몇 가지 주요한 패턴을 살펴볼 것이다.
즉시 실행 함수는 함수를 정의함과 동시에 바로 실행되는 함수이다. 이 패턴은 변수의 스코프를 한정하기 위해서 주로 사용되며, 글로벌 스코프에 변수를 추가하지 않아도 되기 때문에 코드의 충돌 없이 구성 요소를 독립적으로 유지할 수 있다.
예시:
(function() {
const localVar = "I'm a local variable";
console.log(localVar);
})();
console.log(typeof localVar); // "undefined"
여기에서 localVar
은 IIFE 내부에서만 접근 가능하며, 외부에서는 undefined
로 나타난다.
클로저는 내부 함수가 외부 함수의 맥락에 접근할 수 있는 JavaScript의 특성을 말한다. 이는 내부 함수가 외부 함수의 변수에 접근할 수 있도록 하며, 외부 함수의 실행이 끝난 후에도 변수가 사라지지 않게 한다.
예시:
function outerFunction() {
const outerVar = "I'm an outer variable";
function innerFunction() {
console.log(outerVar); // "I'm an outer variable"
}
return innerFunction;
}
const closure = outerFunction();
closure();
여기에서 innerFunction
은 outerFunction
의 outerVar
변수에 접근할 수 있다. outerFunction
이 실행을 마쳤음에도 closure()
를 통해 outerVar
에 접근이 가능하다.
함수 표현식은 종종 이벤트 리스너나 타이머, 비동기 작업 등에 사용되는 콜백 함수로 사용된다. 콜백 함수는 특정 작업이 완료된 후에 실행될 함수를 말한다.
예시:
setTimeout(function() {
console.log("This will run after 2 seconds");
}, 2000);
setTimeout
함수는 지정된 시간(밀리초) 후에 콜백 함수를 실행한다.
함수 표현식을 사용할 때, 이름을 가지지 않는 함수를 정의하는 경우가 많다. 이러한 함수를 익명 함수라고 한다. 익명 함수는 주로 한 번만 사용될 함수나, 함수의 이름을 별도로 지정할 필요가 없는 곳에 사용된다.
예시:
const multiply = function(a, b) {
return a * b;
};
여기서 함수는 multiply
변수에 할당되며, 별도의 이름을 가지지 않는다.
유연성: 함수 표현식은 변수, 배열, 객체의 속성 등에 할당될 수 있다. 이러한 특성은 고차 함수 (Higher-order function) 작성 시 유용하다.
익명성: 이름을 지정할 필요 없이 즉석에서 함수를 생성하고 사용할 수 있다. 이는 코드의 간결성과 유연성을 높여준다.
코드의 구조화: 즉시 실행 함수와 같은 패턴을 사용하면 코드의 모듈화와 구조화가 용이하다.
두 방식 모두 장점이 있으므로, 상황과 필요에 따라 적절한 방식을 선택하면 된다.
JavaScript는 다양한 방식으로 함수를 정의하고 사용할 수 있게 해주는 유연한 언어이다. 이러한 다양성은 코드의 표현력을 높여주지만, 동시에 코드의 구조와 작동 방식을 잘 이해하고 사용해야 한다. 함수의 선언과 호출 방식을 올바르게 선택하면, 코드의 가독성과 유지 보수성을 크게 향상시킬 수 있다.
좋은 글이네요. 공유해주셔서 감사합니다.