본문 바로가기

JavaScript

[JavaScript] 함수 표현식

함수 선언 방식 외에 함수 표현식을 사용해서 함수를 만들 수 있다.


  
// 함수 선언문 방식
function sayHi() {
alert( "Hello" );
}
// 함수 표현식
let sayHi = function() {
alert( "Hello" );
};

또한 변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있다.


  
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
let func = sayHi; // (2) 함수 복사
func(); // Hello // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello // 본래 함수도 정상적으로 실행됩니다.
  1. (1)에서 함수 선언 방식을 이용해 함수를 생성한다. 생성한 함수는 sayHi라는 변수에 저장.
  2. (2) 에선 sayHi를 새로운 변수 func에 복사한다. 이때 sayHi 다음에 괄호가 없다는 점에 유의한다. 괄호가 있었다면 func = sayHi() 가 되어 sayHi 함수 그 자체가 아니라, 함수 호출 결과(함수의 반환 값)  func에 저장된다.
  3. 이젠 sayHi()  func()로 함수를 호출할 수 있게 된다.

함수 sayHi는 아래와 같이 표현식을 사용해서 정의할 수 있다.


  
let sayHi = function() {
alert( "Hello" );
};
let func = sayHi;
// ...

* 함수 표현식에 세미 콜론을 붙이는 이유 *

  • if { ... }, for { }, function f { } 같이 중괄호로 만든 코드 블록 끝엔 ;이 없어도 된다.
  • 함수 표현식은 let sayHi = ...;과 같은 구문 안에서 값의 역할을 합니다. 코드 블록이 아니고 값처럼 취급되어 변수에 할당된다. 모든 구문의 끝엔 세미 콜론 ;을 붙이는 게 좋다. 함수 표현식에 쓰인 세미 콜론은 함수 표현식 때문에 붙여진 게 아니라, 구문의 끝이기 때문에 붙여졌다.

- 콜백 함수

: 매개변수 3개가 있는 함수가 있다. ask(question, yes, no) 각 매개변수는 question: 질문,  yes: yes라고 답한 경우 실행되는 함수 no: no라고 답한 경우 실행되는 함수 이다.

함수는 반드시 question을 해야 하고, 사용자의 답변에 따라 yes 나 no로 호출해야한다.


  
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "동의하셨습니다." );
}
function showCancel() {
alert( "취소 버튼을 누르셨습니다." );
}
// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);

이렇게 함수를 작성하는 방법은 면대면으로 질문하는 것보다 컨펌창을 띄워 질문을 던지고 답변을 받으면 간단하게 설문조사를 진행할 수 있다.

함수 ask의 인수, showOk와 showCancel 은 "콜백 함수" 또는 "콜백" 이라고 불린다.

콜백 함수는 함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 "나중에 호출"하는 개념이다. 위 예시에선 사용자가 yes라고 대답한 경우 showOk가 콜백이 되고, no라고 대답한 경우 showCancel이 콜백이 된다.

 

이렇게 함수 표현식을 사용하면 코드 길이가 짧아진다.


  
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"동의하십니까?",
function() { alert("동의하셨습니다."); },
function() { alert("취소 버튼을 누르셨습니다."); }
);

ask안의 이름 없이 선언한 함수를 익명함수라고 부른다. 익명함수는 변수에 할당된 게 아니기 때문에 ask 바깥에선 접근할 수 없다. 

 

- 함수 표현식 vs 함수 선언문


  
// 함수 선언문 : 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다.
function sum(a, b) {
return a + b;
}
// 함수 표현식 : 표현식이나 구문 구성 내부에 생성된다.
let sum = function(a, b) {
return a + b;
};

첫 번째로 위 코드처럼 함수의 위치가 다르고, 두 번째 차이는 자바스크립트 엔진이 언제 함수를 생성하는지 이다.

함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성한다. 따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있다. 위 코드로 보면 let sum = function ... 의 우측에 도달했을 때 함수가 생성된다. 이때 이후부터 해당 함수를 사용할 수 있다.

함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있다.

자바스크립트 내부 알고리즘 때문에 스트립트를 실행하기 전, 준비단계에서 전역에 선언된 함수 선언문을 찾고, 해당 함수를 생성한다. 스크립트가 실행되기 전 초기화단계에서 함수 선언방식으로 정의한 함수가 생성된다.

스크립트는 함수 선언문이 모두 처리된 이후에 실행되기 때문에 스크립트 어디서든 함수 선언문으로 선언한 함수에 접근할 수 있다.


  
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}

함수 선언이 스크립트 실행 전 선언되기 때문에 함수 선언 위에 있어도 실행이 된다.


  
sayHi("John"); // error!
let sayHi = function(name) { // (*) 마술은 일어나지 않습니다.
alert( `Hello, ${name}` );
};

함수 표현식은 함수가 선언되기 전에는 호출이 불가능 하다.

 

세번째 차이점은 스코프이다.

엄격 모드에서 함수 선언문이 코드 블록 내에 위치하면 해당 함수는 블록 내 어디든 접근할 수 있다. 하지만 블록 밖에서는 함수에 접근하지 못한다.


  
let age = prompt("나이를 알려주세요.", 18);
// 조건에 따라 함수를 선언함
if (age < 18) {
function welcome() {
alert("안녕!");
}
} else {
function welcome() {
alert("안녕하세요!");
}
}
// 함수를 나중에 호출합니다.
welcome(); // Error: welcome is not defined

변수 age가 있고, 변수의 값에 따라 welcome()을 다르게 정의해야 하는데 welcome()함수가 나중에 선언되어서 의도한 대로 코드가 작동되지 않는다.


  
let age = 16; // 16을 저장했다 가정합시다.
if (age < 18) {
welcome(); // \ (실행)
// |
function welcome() { // |
alert("안녕!"); // | 함수 선언문은 함수가 선언된 블록 내
} // | 어디에서든 유효합니다
// |
welcome(); // / (실행)
} else {
function welcome() {
alert("안녕하세요!");
}
}
// 여기는 중괄호 밖이기 때문에
// 중괄호 안에서 선언한 함수 선언문은 호출할 수 없습니다.
welcome(); // Error: welcome is not defined

의도된 대로 코드를 짜고 싶다면 함수 표현식을 사용하면 가능하다.


  
let age = prompt("나이를 알려주세요.", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("안녕!");
};
} else {
welcome = function() {
alert("안녕하세요!");
};
}
welcome(); // 제대로 동작합니다.

물음표 연산자를 사용하여 더 단순화 하게 코드를 짤 수 있다.


  
let age = prompt("나이를 알려주세요.", 18);
let welcome = (age < 18) ?
function() { alert("안녕!"); } :
function() { alert("안녕하세요!"); };
welcome(); // 제대로 동작합니다.

* 함수 생성시 선언문을 이용해 함수를 선언하는것을 고려한다. *

'JavaScript' 카테고리의 다른 글

[JavaScript] 객체  (0) 2022.04.26
[JavaScript] 화살표 함수  (0) 2022.04.24
[JavaScript] 함수  (0) 2022.04.24
[JavaScript] switch문  (0) 2022.04.24
[JavaScript] 반복문의 출력값 예상하기  (0) 2022.04.24