[모던JS] 020. [기본] 함수 표현식(콜백 함수, 익명 함수)
함수 표현식 (Function Declaration)이란?
자바스크립트에서는 함수를 생성하는 방법이 두 가지가 있다.
- 함수 선언식 (Function Declaration)
- 함수 표현식 (Function Expression)
// 함수 선언식
function myFunction() {
// 함수 body
}
// 함수 표현식
let myFunction = function() {
// 함수 body
}
함수 선언식은 fuction을 이용해서 함수를 선언하는 것이고, 함수 표현식은 변수를 선언하고 그 변수의 값으로 함수를 초기화 하는 것이다.
그런데 함수 선언식에서는 function 함수명() {함수body} 형태이지만 함수 표현식에서는 함수명이 빠져서 function() {함수body}가 된다. 함수명은 이미 변수명으로 만들었기 때문이다. 여기에서 선언된 함수가 이 변수 그 자체이기 때문에 변수명으로 대체한다.
함수 표현식에서의 함수 호출
함수 표현식으로 함수를 선언해도 기존처럼 함수를 호출할 수 있다.
function myFunction = function() {
console.log('hello');
}
myFunction(); // hello
console.log(myFunction); // 함수 괄호가 빠진 형태
// 함수의 내용이 출력된다.
// function myFunction = function() {
// console.log('hello');
// }
console.log(myFunction()); // 'hello', undefined
// 함수의 내용이 console.log인데 이는 콘솔에 함수에서 반환된 값을 출력하는 함수다.
// 그런데 함수 내부에서 console.log는 실행만 되는 함수이지 값을 반환하는 함수가 아니다.
// 따라서 함수가 한 번 실행된 후 값으로 undefined가 반환된다.
함수 표현식에서의 함수 복사
함수 표현식으로 함수를 선언하면 변수에 '값'을 할당하는 것이기 때문에 값을 다른 변수에 복사하듯이 함수를 복사할 수 있다.
function sayHi() {
alert( 'hello' );
}
let sayHiCopy = sayHi;
sayHi(); // hello
sayHiCopy() // hello
함수를 복사할 때 sayHi를 사용하고 소괄호를 적지 않았는데, 위에서 봤던 예시와도 같다. 소괄호를 빼면 함수 코드 자체가 반환되기 때문에 함수 코드 자체가 변수에 복사되지만,
let sayHiCopy = sayHi(); 처럼 소괄호를 넣게 되면 함수가 실행되고 나서의 반환 값이 복사되게 된다. 이 경우 alert창을 출력하는 함수 외 반환하는 값이 없기 때문에 undefined가 복사되는 것이다.
즉 이 상태에서 sayHiCopy();로 함수를 호출하면 함수가 아니라는 에러가 출력된다.
function sayHi() {
alert( 'hello' );
}
let sayHiCopy = sayHi;
sayHi();
함수 표현식에 세미콜론이 들어가는 이유
함수 선언식에서는 세미콜론을 넣지 않는다.
function myFunction() {}
그런데 함수 표현식에서는 세미콜론을 넣는다.
let myFunction = function() {};
이유는 중괄호로 만든 코드블럭의 끝엔 세미콜론이 들어가지 않기 때문이다.
if {}, for{}, function() {}
콜백 함수 (callback function)
함수의 인수로 함수가 쓰이는 함수를 콜백 함수라고 한다.
함수는 매개변수를 설정할 수 있다. 함수 매개변수의 역할은 외부에서 값을 받아 함수 내부로 전달할 수 있게 해준다. 그런데 값에 함수를 넣게 되면 함수 내부에서 조건에 따라 특정 동작이 가능하게 할 수도 있다.
function ask(question, yes, no) {
if (confirm(question)) {
yes();
} else {
no();
}
}
function showOk() {
alert( '동의하셨습니다.' );\
}
function showCancel() {
alert( '취소 버튼을 누르셨습니다.' );
}
ask('동의하십니까?', showOk, showCancel);
코드 해석
- ask라는 함수를 선언하고 매개변수로 question, yes, no 세 개를 받도록 했다.
- 함수의 실행 내용으로는 if문을 사용해서 question 인수로 받은 내용으로 (텍스트가 될 것이다) confirm 대화상자를 연다. 그리고 true면 yes() 함수가 실행되고 false면 else 다음인 no() 함수를 실행한다. confirm 대화상자에서 true는 확인을 누르면 반환되는 값이고 false는 취소를 눌렀을 때 반환되는 값이다.
- 그러면 yes(), no()라는 함수를 외부에서 선언해주어야 한다.
- showOk() 함수를 선언해서 동의하셨습니다. alert창을 띄우도록 했고 showCancel도 유사하게 선언했다.
- 마지막 라인에서 ask()를 통해 함수를 선언했다.
- ask 함수를 호출하면서 인수로 alert에 confirm으로 띄우는 question 매개변수를 "동의하십니까?"로 지정하고, 참일 때 실행할 함수를 showOk, 거짓일 때 실행할 함수를 showCancel로 설정했다.
그런데 위 함수를 function() {}과 같은 함수 선언식이 아니라 변수에 값을 담는 함수 표현식으로 작성한다면 코드를 더 간결하게 작성할 수 있다.
function ask(question, yes, no) {
if (confirm(question)) {
yes();
} else {
no();
}
}
ask(
'동의하십니까?',
function() {
alert('동의하셨습니다.');
},
function() {
alert('취소를 버튼을 누르셨습니다.');
}
)
익명 함수 (anonymous function)
위 함수를 보면 ask 안에 함수가 선언되어 있다. 그런데 함수 이름이 없다. 이것을 익명 함수라 한다. 이 함수들은 별도로 외부에서 function을 통해 선언된 것이 아니기 때문에 외부에서 호출 할 수 없고 ask 내부에서만 접근할 수 있다. 따라서 외부에서 호출할 함수명이 필요가 없는 것이다. 그래서 이렇게 익명 함수로 작성한다.
함수 선언문 vs 함수 표현식 비교
함수 선언문과 함수 표현식은 둘 다 함수를 만드는 방법이다. 그런데 어떤 것을 사용해야 하느냐는 약간의 차이로 갈리지만 처음부터 이 모든 차이를 고려하긴 어렵고, 일반적으로는 함수 선언식을 먼저 고려하는 것이 가독성 면에서도 직관적이고, 함수를 선언하기도 전에 호출할 수도 있기 때문에 장점이 조금 더 많다.
문법적 차이
- 함수 선언문
- 함수는 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다.
function sum(a, b) {
return a + b;
}
- 함수 표현식
- 함수는 표현식이나 구문 구성(synatax construct) 내부에 생성된다. 아래 예시에선 함수가 할당 연산자 =를 이용해 만든 할당 표현식 우측에 생성되었다.
let sum = function(a, b) {
return a + b;
};
함수 생성 시기 차이
- 함수 선언문
- 함수 선언문은 어디에서든 함수를 호출할 수 있다.
- 즉 함수를 선언하기 전, 위의 코드 라인에서도 함수를 호출할 수 있다는 것이다.
- 함수 표현식
- 함수 표현식은 코드를 쭉 실행하다 let sum = function...에 흐름이 도달했을 때 함수가 생성된다.
- 즉 함수를 호출할 수 있는 시기는 함수가 선언된 이후부터 호출이 가능하다. 함수가 정의되지도 않았는데 함수를 호출할 수 없다.
// 함수 선언식
sayHi('장원영');
function sayHi(name) {
alert(`Hello, ${name}`);
}
// 함수 선언 전 함수 호출 가능
// 함수 표현식
sayHi('장원영');
let sayHi(name) {
alert(`Hello, ${name}`);
}
// 에러 발생, 함수 선언 전 호출 불가능
스코프 차이
- 함수 선언문
- 함수 선언문으로 선언된 함수가 다른 코드의 안에 있을 때는 그 코드블럭 안에서만 호출이 가능하다.
- 함수 표현식
- 함수 표현식으로 선언된 함수는 그 함수가 선언된 코드블럭 밖에서도 호출이 가능하다.
let age = 16;
if (age < 18>) {
welcome(); // 실행됨
function welcome() {
alert('안녕');
}
} else {
function welcome() {
alert('안녕하세요');
}
}
welcome(); // 실행안됨
// 중괄호 밖에서는 코드블럭 내부에서 함수 선언문으로 선언된 함수를 호출할 수 없음.
let age = prompt('나이를 알려주세요', 18)
let welcome;
if (age < 18) {
welcome = function() {
alert('안녕');
};
} else {
welcome = function() {
alert('안녕하세요');
};
}
welcome; // 실행됨
그리고 물음표 연산자로 위 코드를 간결하게 할 수 있다. 물음표 함수는 (condition) ? a : b 형태로 쓰며 condition이 true이면 a를 반환하고 false이면 b를 반환한다.
let age = prompt('나이를 알려주세요', 18)
let welcome = (age<18) ?
function { alert('안녕'); }:
function { alert('안녕하세요')};
welcome(); // 실행됨
'Programing > JavaScript' 카테고리의 다른 글
[모던JS] 022. [기본] 기본 문법 요약 (0) | 2024.03.30 |
---|---|
[모던JS] 021. [기본] 화살표 함수 기본 (0) | 2024.03.30 |
[모던JS] 019. [기본] 함수 (함수선언식, 매개변수, 지역변수, 전역변수, return, 함수명명규칙), (0) | 2024.03.28 |
[모던JS] 018. [기본] switch문 (0) | 2024.03.28 |
[모던JS] 017. [기본] while과 for 반복문 (0) | 2024.03.28 |
댓글