출처 : https://javascript.info/function-expressions
Function expressions
javascript.info
함수 표현식
자바스크립트에서 함수는 "마법 같은 언어 구조"가 아니라 특별한 종류의 값임.
우리가 이전에 사용했던 문법은 함수 선언(Function Declaration)이라고 함.
:
function sayHi() {
alert( "Hello" );
}
반면 , 함수 표현식 (Function Expression)은 함수 표현식을 만드는 또 다른 문법임.
이 문법을 사용하면 어떤 표현식의 중간에서 새로운 함수를 생성할 수 있음.
예를 들어 :
let sayHi = function() {
alert( "Hello" );
};
위 코드에서 변수 SayHi에 함수 리터럴 function () { alert("Hello");}가 할당됨.
즉 할당 표현식의 우변에서 함수가 생성되었으므로 이것은 함수 표현식임.
참고 : 함수 표현식에서는 함수 이름을 생략할 수 있음.
이 경우 익명 함수 (anoymous function)가 생성되며 , 위 예제처럼 바로 변수에 할당할 수 있음.
위의 코드에도 함수의 이름을 따로 설정해주진 않았음.
이와 같이 함수를 즉시 변수에 할당하면 "함수를 생성해서 변수 sayHi에 넣는다 " 는 의미가 됨.
보다 복잡한 상황에서는 함수가 생성되자마자 바로 호출되거나 나중에 실행될 목적으로 스케줄링 될수도 있고 , 어딘가에 저장되지 않아 익명으로 남기도 함.
함수는 값이다
다시 한번 강조하면 함수가 어떻게 생성되었든 함수는 하나의 값임.
위의 두 예제 모두 sayHi 변수에 함수를 저장함.
예를 들어 아래와 같이 alert를 사용하여 함수 값을 출력할 수 있음 :
function sayHi() {
alert( "Hello" );
}
alert( sayHi ); // 함수의 소스 코드(문자열 표현)가 출력됨
함수를 실행하는 것이 아니라 alert으로 바로 함수를 호출해도 출력이 됨.
함수 = 값
어떤 언어에서는 함수 이름을 언급할 때 자동으로 실행되지만 자바스크립트는 그렇지 않음.
자바스크립트에서 함수는 값이므로 다른 값들과 동일하게 다룰 수 있음.
예를 들어 함수를 다른 변수에 복사할 수 있음 :
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
let func = sayHi; // (2) 함수를 복사 (괄호 없이 sayHi를 참조)
func(); // "Hello" 출력 (3) 복사된 함수를 호출
sayHi(); // "Hello" 출력 – 원래 함수도 정상 호출됨
위 코드의 동작을 자세히 설명하면 다음과 같음 :
1. (1) 함수 선언문으로 sayHi 함수를 생성하고 , 변수 sayHi에 저장함.
2. (2) 변수 func에 sayHi 함수를 복사함.
주의: 여기서 sayHi 뒤에 괄호가 없으므로 실제 호출이 아니라 함수 자체를 복사하는 것임.
3. (3) 이제 함수는 sayHi() 뿐 아니라 func() 로도 호출할 수 있음.
함수 표현식을 사용하여 sayHi를 선언하는 경우도 동일함 :
let sayHi = function() { // (1) 함수 생성
alert( "Hello" );
};
let func = sayHi; // (2)
// ...
모든 동작은 위와 동일하게 진행됨.
왜 세미콜론이 있을까?
함수 표현식은 아래와 같이 할당문 내에서 생성됨 :
let sayHi = function() {
// ...
};
여기서 할당문이 끝나면 세미콜론(;)을 붙임.
이 세미콜론은 함수 문법의 일부가 아니라 , 단순히 할당문(statement)의 끝을 표시하기 위함임.
예를 들어 , let sayHi = 5; 에서도 세미콜론이 사용되듯이 , 함수 할당에도 동일하게 사용됨.
콜백 함수
함수를 값으로 전달하고 함수 표현식을 사용하는 예제를 좀 더 살펴봄.
다음 예제에서는 세 개의 매개변수를 갖는 함수 ask(question , yes , no)를 작성함 :
question : 질문 퀘스트
yes : 사용자의 대답이 "예 " 일 때 실행할 함수
no : 사용자의 대답이 "아니오" 일 때 실행할 함수
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "You agreed." );
}
function showCancel() {
alert( "You canceled the execution." );
}
// 사용 예: 함수 showOk와 showCancel을 인수로 전달
ask("Do you agree?", showOk, showCancel);
위 예제에서 ask 함수의 인자로 전달된 showOk와 showCancel은 콜백(callback) 함수라고 부름.
즉 필요한 시점에 호출될 ( 나중에 "콜백" 되는 ) 함수들임.
다른 함수의 인자로 전달이 되는 함수를 이야기함.
함수 표현식을 사용하여 아래와 같이 더 간결하게 작성할 수도 있음 :
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
여기서 함수들은 ask 함수 호출 내부에 익명 함수로 선언되며 , 외부에서는 접근할 수 없음.
이런 방식은 자바스크립트의 자연스러운 코딩 방식 중 하나임.
함수는 행동을 나타내는 값이다.
일반 값 ( 문자열 , 숫자 등)은 데이터를 나타냄.
함수는 하나의 행동(action)을 나타내며 , 변수 간에 전달할 수 있고 필요할 때 실행할 수 있음.
함수 표현식 vs 함수 선언
두 가지를 구분하는 주요 차이점을 정리하면 다음과 같음.
문법상의 차이
함수 선언(Function Declaration) :
코드의 주 흐름에서 별도의 문 (statement)으로 선언함 .
// 함수 선언문
function sum(a, b) {
return a + b;
}
따로 선언문 자체가 존재함.
함수 표현식 ( Function Expression):
표현식의 일부 (예:할당문)로서 함수를 생성함.
// 함수 표현식
let sum = function(a, b) {
return a + b;
};
따로 선언문을 해준것이 아니라 할당문의 일부에서 함수를 생성한걸 이야기하는 것 같음.
생성 시점의 차이
함수 표현식 :
실행 흐름이 해당 표현식에 도달할 때 함수가 생성됨.
즉 할당문 오른쪽에 있는 함수는 실행이 해당 줄에 도달했을 때 만들어지며 , 그 이후에만 사용할 수 있음.
함수 선언 :
자바스크립트 엔진은 스크립트를 실행하기 전에 전역 또는 블록 내의 함수 선언문들을 먼저 처리함.
따라서 함수 선언문은 코드 어디서든 호출할 수 있음.
두 가지의 차이점은 JS 엔진이 스크립트를 실행하기 전에 먼저 처리를 하느냐 혹은 실행 흐름이 넘어왔을 때 생성이 되는냐 차이인것 같음.
예를 들어 :
sayHi("John"); // "Hello, John" 출력
function sayHi(name) {
alert( `Hello, ${name}` );
}
위 코드는 정상적으로 작동하는데 , 이는 함수 선언이 스크립트 시작 전에 이미 처리 되었기 때문임.
그래서 함수를 위에서 호출하더라도 아래 있는 함수들이 동작하는 것 같음.
만약 이것이 함수 표현식이었다면 , 아래와 같이 호출하면 에러가 발생함 :
sayHi("John"); // 에러 발생
let sayHi = function(name) {
alert( `Hello, ${name}` );
};
함수 표현식의 경우엔 이때 함수가 생성되는건데 아래에 있다보니 아직 실행흐름이 넘어오지 않았고
그러므로 아직 함수가 생성이 되지 않았는데 함수를 호출했으니 함수가 불러와지지 않는다.
블록 스코프에서의 차이
엄격 모드(strict mode)하에서 , 함수 선언문이 코드 블록 내에 있을 경우 그 함수는 해당 블록 내부에서만 유효함.
즉, 블록 밖에서는 접근할 수 없음.
let age = prompt("What is your age?", 18);
if (age < 18) {
function welcome() {
alert("Hello!");
}
} else {
function welcome() {
alert("Greetings!");
}
}
// 여기서는 welcome()이 정의되어 있지 않음
welcome(); // Error: welcome is not defined
이런 경우 함수 표현식을 사용하여 외부 변수에 할당하면 문제를 해결할 수 있음 :
let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("Hello!");
};
} else {
welcome = function() {
alert("Greetings!");
};
}
welcome(); // 정상 호출됨
외부의 변수에 코드 블럭 내의 함수를 할당하여 외부에서도 해당 함수를 이용할 수 있음.
또는 삼항 연산자를 사용해 더 간단하게 작성할수도 있음 :
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ?
function() { alert("Hello!"); } :
function() { alert("Greetings!"); };
welcome(); // 정상 호출됨
언제 함수 선언과 함수 표현식을 선택해야 할까?
일반적으로 함수를 선언할 때는 함수 선언문(Function Declaration) 문법을 우선 고려함.
함수 선언문은 선언 전에 호출할 수 있어 코드 조직에 유리하며 가독성이 좋음.
하지만 , 만약 조건에 따라 함수를 선택하거나 (위의 예시처럼) 함수 선언문이 적합하지 않은 경우에는 함수 표현식(Function Expression) 을 사용하면 됨.
아마 조건에 따라서 필요하지 않은 함수들까지 사용할 필욘 없으니까 함수 표현식을 이용하여 최적화를 하는거 같음.
'언어' 카테고리의 다른 글
| JavaScript specials (JavaScript) (0) | 2025.03.15 |
|---|---|
| Arrow functions, the basics (JavaScript) (0) | 2025.03.14 |
| Functions (JavaScript) (0) | 2025.03.14 |
| The "switch" statement (JavaScript) (0) | 2025.03.14 |
| Loops: while and for (0) | 2025.03.14 |