[JS] 5. 함수 (Function)
함수 (Function) : 일련의 과정을 코드 블록으로 감싸 하나의 단위로 정의한 것
- 자바스크립트의 함수는 객체 타입의 값 → 함수 또한 함수 리터럴 (
functional literal)로 생성할 수 있음 - 일반 객체와 달리, 함수는 호출할 수 있고 함수 객체만의 고유한 프로퍼티를 가짐
함수 정의 (Function Definition) : 함수 호출 이전에 인수를 전달받을 매개변수, 문, 반환값을 지정
함수 선언문이 평가되면 식별자가 암묵적으로 생성되고 함수 객체가 할당되므로, 함수는 정의된다고 할 수 있다.
함수 선언문 (Function Declaration)
- 함수 선언문은 함수 리터럴과 형태가 동일
- 함수 리터럴은 함수 이름을 생략할 수 있으나, 함수 선언문은 함수 이름을 생략할 수 없음
function greet() {
console.log('Hello, world!');
}
greet(); // 'Hello, world!'
함수 표현식 (Function Expression)
- 함수 표현식은 함수 리터럴을 변수에 할당하여 사용
- 함수 표현식은 함수 리터럴을 변수에 할당하여 사용합
const greet = function() {
console.log('Hello, world!');
};
greet(); // 'Hello, world!'
Function 생성자 함수
Function생성자 함수를 사용하여 함수를 동적으로 생성 가능- 코드 가독성이 떨어져 잘 사용하지 않음
const add = new Function('a', 'b', 'return a + b');
console.log(add(2, 3)); // 5
화살표 함수 (Arrow Function)
- 간결한 문법을 제공하며, this 바인딩이 정적으로 결정
- 함수 몸체가 단일 표현식인 경우, 중괄호와
return생략 가능
const greet = () => {
console.log('Hello, world!');
};
greet(); // 'Hello, world!'
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
함수 매개변수 (Argument : 값, Parameter : 변수)
function greet(name) { // 'name'은 매개변수
console.log('Hello, ' + name + '!');
}
greet('Alice'); // 'Alice'는 인수
즉시 호출 함수 IIFE
- 정의와 동시에 실행되는 함수
- 전역 스코프 오염을 방지하기 위해 사용
(function() { ... })();
함수의 호출 방식과 this
this를 바인딩하는 방법 :call,apply,bind
function func(id) {
console.log(this, id, this.name);
}
const obj = { name: 'Kim' };
// bind
const bf1 = func.bind(obj);
bf1(1, '서울');
// apply
func.apply(obj, [ 2, '부산' ]);
// call
func.call(obj, 3, '대구');
순수 함수 (Pure Function) : 함수로서의 함수
- 입력이 같으면 결과도 같다! →
Side Effect가 없다. 즉, 외부의 값을 변경시키지 않아야 한다!
const weeks = ['일', '월', '화', '수', '목', '금', '토'];
const getWeekName = function(weekNo) {
return `${weeks[weekNo]}요일`;
};
const day = new Date().getDay();
console.log(`오늘은 ${getWeekName(day)}입니다!`);
→ 외부에 값을 두지 않고 내부에 값을 두는 클로저를 활용해야 한다!
고차 함수 (Higher-Order Function) : 다른 함수를 인자로 받거나 함수를 반환하는 함수
자바스크립트에서의 함수는 일급 객체 (
First-Class Citizen)
- 변수에 할당 (
Assignment)할 수 있다.- 다른 변수의 인자 (
Argument)로 전달될 수 있다.- 다른 함수의 결과로 반환 (
Return)될 수 있다.→ 함수가 일급 객체이므로, 함수를 데이터와 유사하게 다룰 수 있어 ‘고차 함수’로서 활용될 수 있다.
const double = (n) => { return n * 2; };
console.log(double(4)); // 4 * 2 = 8
const adder = added => num => num + added;
console.log(adder(5)(3)); // 5 + 3 = 8
- 함수의 형태로 반환되는 함수를 모두 고차 함수라 정의할 수 있다.
- 함수는 일급 객체 → 일급 객체로서의 함수는 고차 함수로 활용 가능
함수를 리턴하는 함수를 커리 함수 (
Curry Function)라고 부르던데…?
- 커리 함수라는 용어로, 고차 함수를 ‘함수를 인자로 받는 함수’에만 한정해 사용할 수 있음
- 엄밀히 말하면, 고차 함수가 커리 함수를 포함하는 개념
Array.map() 함수 : 배열의 각 요소에 대해 주어진 함수를 호출한 다음, 그 결과를 새로운 배열로 반환
console.log([1, 2, 3, 4, 5].map((num) => { return num * num; })); // [ 1, 4, 9, 16, 25 ]
Array.filter() 함수 : 배열의 요소 중에 주어진 조건을 만족하는 요소만을 추출하여 새로운 배열로 반환
console.log([1, 2, 3, 4, 5].filter((num) => { return num % 2 === 0 })); // [ 2, 4 ]
Array.reduce() 함수 : 배열의 각 요소에 대해 주어진 함수를 실행하고, 그 결과를 누적하여 하나의 값으로 반환
console.log([1, 2, 3, 4, 5].reduce((accumulator, currentValue)
=> { return accumulator + currentValue;}, 0)); // 15
Array.forEach() 함수 : 배열의 각 요소에 대해 주어진 함수를 실행 (반환값이 존재하지 않음)
[1, 2, 3, 4, 5].forEach((num) => { console.log(num); }); // 1부터 5까지 순서대로 출력
콜백 함수 (Callback Function) : 매개변수를 통해 다른 함수의 내부로 전달되는 함수
setTimeout(() => { console.log(`출력`); }, 1);
- 고차 함수의 인자로 전달되어, 특정 동작을 수행하거나 완료 시에 호출
- 콜백 함수를 전달받은 고차 함수는 함수 내부에서 이 콜백 함수르 호출 (
Invoke)할 수 잇음 - 부르는 조건에 따라서 콜백 함수의 실행 조건을 결정할 수 있음
- 콜백 함수를 전달받은 고차 함수는 함수 내부에서 이 콜백 함수르 호출 (
- 콜백 함수를 언제 호출하는지에 따라, 자바스크립트 엔진이 콜백 함수의 호출 시점을 결정
- 함수가 실행되면 콜 스택에 함수를 넣었다가, 함수에서 반환이 일어날 때 가장 위쪽에서 해당 함수를 꺼냄
- 이벤트 루프는 콜 스택과 테스크 큐를 주시하고 있다가, 스택이 비어 있으면 큐의 첫번째 콜백을 스택에 쌓아 실행
매개변수를 통해 다른 함수로 전달되는 함수는 콜백 함수, 매개변수를 통해 콜백 함수를 전달받는 함수는 고차 함수!
// printString : 두개의 함수와 하나의 문장을 매개변수로 사용하는 고차함수 const printString = (callbackHof, callback_only, str) => { str +=' 반이고'; callbackHof( callback_only, str ); } // concatFirst : printString의 매개변수로 활용되는 콜백함수이면서, // 하나의 함수와 하나의 문장을 매개변수로 사용하는 고차함수 const concatFirst = (callback_only, str) => { callback_only(str); } // concatAgain : concatFirst의 매개변수로 활용되는 콜백함수 const concatAgain = (str) => { str += ' 가만히 있으면 반이라도 간다'; console.log(str); } printString(concatFirst, concatAgain, '시작은'); // 시작은 반이고 가만히 있으면 반이라도 간다