함수 선언 방식 외에 함수 표현식을 사용해서 함수를 만들 수 있다.
// 함수 선언문 방식
function sayHi() {
alert( "Hello" );
}
// 함수 표현식
let sayHi = function() {
alert( "Hello" );
};
또한 변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있다.
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
let func = sayHi; // (2) 함수 복사
func(); // Hello // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello // 본래 함수도 정상적으로 실행됩니다.
- (1)에서 함수 선언 방식을 이용해 함수를 생성한다. 생성한 함수는 sayHi라는 변수에 저장.
- (2) 에선 sayHi를 새로운 변수 func에 복사한다. 이때 sayHi 다음에 괄호가 없다는 점에 유의한다. 괄호가 있었다면 func = sayHi() 가 되어 sayHi 함수 그 자체가 아니라, 함수 호출 결과(함수의 반환 값) 가 func에 저장된다.
- 이젠 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 |