스크립트를 작성하다 보면 사용자가 로그인이나 로그아웃을 했을 때 안내 메시지를 보여주는 동작 같은 경우 등 유사한 동작을 하는 코드가 여러 곳에서 필요할 때가 있다. 함수를 이용하면 중복 없이 유사한 동작을 하는 코드를 여러 번 호출할 수 있다.
주요 코드 흐름을 차지하는 방식 - 함수 선언문
function add(x, y){
return x + y; }
console.log(add(2,7));
표현식 형태로 선언된 함수 - 함수 표현식
함수를 호출했을 때 함수를 호출한 그곳에 특정 값을 반환하게 할 수 있다. 이때 이 특정 값을 반환 값이라고 부른다.
지시자 return은 함수 내 어디서든 사용할 수 있다. 실행 흐름이 return을 만나면 함수 실행은 즉시 중단되고 함수를 호출한 곳에 값을 반환한다.
함수도 값으로 인식한다.
let sayHi = function() {
alert("hello");
}; // 함수 표현식
function sayHi2() {
alert( "Hello" );
}
let func = sayHi2; // 함수 복사
func(); // 복사한 함수 실행 (정상 실행됨)
sayHi2();
sayHi();
// 모두 같음.
함수 표현식의 끝에 세미콜론이 붙는 이유
기본적인 함수 선언문과 같이 중괄호로 만든 코드 블록 끝에는 ; 가 없어도 되지만,
함수 표현식은 let sayHi = … ; 와 같이 구문 안에서 값의 역할을 한다.
따라서 함수 표현식에 쓰인 세미 콜론은 함수 표현식 때문에 붙여진 것이 아니라, 구문의 끝이기 때문에 붙여진 것이다.
함수를 값처럼 전달하는 예시 - 콜백 함수
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "동의하셨습니다." );
}
function showCancel() {
alert( "취소 버튼을 누르셨습니다." );
}
// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
위에서 작성된 ask 함수는 매개변수로 함수를 받는다.
함수 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 바깥에서는 접근할 수 없다.
자바스크립트를 사용하다 보면 콜백을 활용한 코드를 자주 만나게 된다. 이런 코드는 자바스크립트의 정신을 대변한다.
<aside> 💡
함수는 ‘동작’을 나타내는 값.
문자열이나 숫자 등의 일반적인 값들은 데이터를 나타내지만,
함수는 하나의 동작을 나타낸다.
동작을 대변하는 값인 함수를 변수 간 전달하고, 동작이 필요할 때 이 값을 실행할 수 있다.
</aside>
함수 표현식 vs 함수 선언문
화살표 함수
함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있다.
let func = (arg1, arg2 …argN) ⇒ expression
함수 func은 화살표 우측의 표현식을 평가하고 평가 결과를 반환한다.
아래 함수 표현식의 축약 버전이라고 볼 수 있다.
let func = function(arg1, arg2, ...argN){
return expression;
};
인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략할 수 있다.
let double = n ⇒ n*2;
인수가 하나도 없을 땐 괄호를 비워놓으면 된다. (이때, 괄호를 생략할 수 있다.)
let sayHi = () ⇒ alert(”안녕하세요!”);
화살표 함수를 함수 표현식과 같은 방법으로 사용 가능하다.
아래와 같이 함수를 동적으로 만들 수 있다.
let age = prompt("나이를 알려주세요." , 18);
let welcome = (age<18) ?
() => alert('안녕') :
() => alert('안녕하세요!");
welcome();
본문이 여러 줄인 화살표 함수
화살표 오른쪽에 있는 표현식이나 구문이 여러 개인 함수를 작성할 경우
중괄호 안에 평가해야 할 코드를 작성하면 된다.
그리고 return 지시자를 사용하여 명시적으로 결괏값을 반환해야 한다.
let sum = (a, b) => {
let result = a + b;
return result;
};
alert(sum(1, 3));
호이스팅
→ 상수나 변수에 함수를 대입했을 경우와 화살표 함수를 이용하여 함수를 선언했을 때에는 호이스팅되지 않는다. 함수 생성 시점이 다름!
<aside> 💡
함수는 값이다. 따라서 함수도 값처럼 할당, 복사, 선언할 수 있다.
</aside>
일급 객체의 특성
→ 함수를 데이터(string, number, boolean, array, object) 다루듯이 다룰 수 있다.
여기서 데이터를 다룬다는 의미는 변수에 값을 할당할 수 있다는 의미와 상통하므로, 함수 역시 할당이 가능하다고 해석될 수 있다.
할당
function isOddNum (number) {
console.log(
(number % 2 ? '홀' : '짝')
+ '수입니다.'
);
return number % 2 ? true : false;
};
const checkIfOdd = isOddNum; // 뒤에 괄호 없음 유의
console.log(checkIfOdd(23));
--------------------------
let x = 7, y = 3;
let func1 = (a, b) => a + b;
let func2 = (a, b) => a - b;
console.log(func1(x, y), func2(x, y));
func1 = func2
console.log(func1(x, y), func2(x, y));
함수를 다른 함수의 인자로 전달하기
전달받는 함수: 고차 함수
→ 함수를 전달인자 또는 매개변수로 받거나, 함수를 리턴하는 함수
전달되는 함수: 콜백 함수
let list = [1, 2, 3, 4, 5];
function doInArray (array, func) {
for (item of array) {
func(item);
}
}
// console.log - console이란 객체에서 log란 키에 할당된 함수
doInArray(list, console.log);
→ doInArray : 고차함수
function doNTimes (func, repeat, x, y) {
let result = x;
for (i = 0; i < repeat; i++) {
result = func(result, y);
}
return result;
}
console.log(
doNTimes((x, y) => x * y, 3, 5, 2),
doNTimes((x, y) => x / y, 3, 5, 2),
);
인자로 전달된 함수들: 변수나 상수에 할당되지 않아 이름이 없음 - 익명 함수
함수를 결과값으로 반환하기
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
const mul = (a, b) => a * b;
const div = (a, b) => a / b;
function comb3ArmFuncs(armFunc1, armFunc2, armFunc3) {
return (x, y) => armFunc3(armFunc2(armFunc1(x, y), y), y);
}
const add_mul_sub = comb3ArmFuncs(add, mul, sub);
const mul_add_div = comb3ArmFuncs(mul, add, div);
const div_add_mul = comb3ArmFuncs(div, add, mul);
console.log(
add_mul_sub(10, 4),
mul_add_div(10, 4),
div_add_mul(10, 4)
);