프로그래밍 언어의 함수는 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행단위로 정의한 것이다.
코드의 재사용을 높일 수 있다!
함수 선언문과 표현식
function add(x,y){ return x+y; }; // 함수선언문 const add = function(x,y){ return x+y; }; // 함수 표현식
둘의 차이는 함수 선언문은 함수 호이스팅이 발생,
함수 표현식은 변수 호이스팅이 발생한다.
자바스크립트에서 함수는 일급객체로 취급한다.
즉, 함수를 변수에 할당할 수 있기 때문에, 함수를 배열의 요소나 객체의 속성값으로 저장할 수 있고 함수를 데이터(string, number, boolean, array, object)처럼 다룰 수 있다.
일반 객체와 차이점으로는 일반 객체는 호출할 수 없지만 함수 객체는 호출할 수 있으며 함수 객체 고유의 데이터 프로퍼티(arguments, caller, length, name, prototype)를 소유하며 일반객체의 프로퍼티도 상속받는다.
(일반객체 프로퍼티 = Ojbect.prototype 객체의 프로퍼티로는 __proto__ 접근자 프로퍼티 등이 있다.)
위에서 말한것 처럼 여러개가 있지만 일부만 살펴보자
arguments 프로퍼티 값은 arguments객체다. 함수 호술 시 전달된 인수들의 정보를 담은 유사 배열 객체이며, 함수 내부에서 지역 변수처럼 사용된다.
만약 인수가 매개변수보다 많다면 arguments 객체에 따로 저장된다.
예시) 가변함수에 유용한 예시
//ES6 문법 Rest파라미터 사용
finction sum6(...args){
args.reduce((pre,cur)=> pre+cur,0)
}
//ES5 문법 arguments 객체를 배열로 반환
function sum5(){
const array = Array.prototype.slice.call(arguments);
return array.reduce(function(pre,cur){
return pre+cur;
},0);
}
console.log(sum5(1,2)) // 3
console.log(sum6(1,2)) // 3
console.log(sum5(1,2,3,4,5)) //15
console.log(sum6(1,2,3,4,5)) //15
함수를 정의할 때 선언한 매개변수의 개수를 가리킨다.
function foo(){}
console.log(foo.length); //0
function bar(x,y,z){
return x+y+z;
}
console.log(bar.length); //3
단, arguments 객체의 length 와 함수 객체의 length 값은 다를 수 있다. 둘은 각각 인자의 개수, 매개변수의 개수를 가리킨다.
함수의 이름을 나타낸다.
ES5에서 익명 함수 표현식의 경우 name프로퍼티는 빈문자열을 갖고 ES6에서는 함수 객체를 가리키는 식별자를 값으로 가진다.
생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor 만이 소유하는 프로퍼티다.
(function () {}).hasOwnProperty("prototype"); // true
({}).hasOwnProperty("prototype"); // false
고차 함수(higher order function)는 함수를 전달인자(argument)로 받을 수 있고, 함수를 리턴할 수 있는 함수이다.
다른 함수(caller)의 전달인자(argument)로 전달되는 함수
--> 이 두 개념은 서로 상관관계가 있어서 같이 알아두자!
수준 높은 추상화가 가능하기 때문이다.
추상화? 복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는 것 이라고 생각하면 편하다.
고차 함수 = 함수를 전달받거나 함수를 리턴한다 = 사고(함수)에 대한 복잡한 로직은 감추어져 있다 => 사고 수준에서의 추상화
일반적인 값의 추상화와 함수의 추상화보다 보다 높은 수준에서 생각할 수 있다.
예시)
function double(num) {
return num * 2;
}
function doubleAdder(added, func) {
const doubled = func(added);
return function (num) {
return num + doubled;
};
}
/*
* 함수 doubleAdder는 고차 함수이다.
* 함수 doubleAdder의 인자 func는 함수 doubleAdder의 콜백 함수다.
* 함수 double은 함수 doubleAdder의 콜백으로 전달되었습니다.
즉, 함수 double은 고차 함수 doubleAdder의 콜백함수가 되는 것이다.
*/
// doubleAdder(5, double)는 함수이므로 함수 호출이 가능하다.
doubleAdder(5, double)(3); // 13
// doubleAdder가 리턴하는 함수를 변수에 저장할 수 있다. (일급 객체)
const addTwice3 = doubleAdder(3, double);
addTwice3(2); // 8
js에 기본적으로 내장 되어있는 고차함수이며 배열 메소드들 중 일부가 고차함수에 해당한다.
오늘은 이 중에서 map, filter, reduce 에 대해 알아보자.
먼저 3개의 내장 메서드 모두 Array의 내장 메서드이며 원본배열을 손상시키지 않는다.
또한 인자로 콜백함수를 받는다.
arr.map(callback(currentValue[, index[, array]])[, thisArg])
map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다.
arr.filter(callback(element[, index[, array]])[, thisArg])
filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.
각 요소를 시험할 함수(콜백함수)가 true를 반환하면 요소를 유지하고, false를 반환하면 버린다.
arr.reduce(callback[, initialValue])
reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서 (reducer) 함수를 실행하고, 하나의 결과값을 반환한다.
리듀서 함수는 네 개의 인자를 가집니다.
1.누산기 (acc)
2.현재 값 (cur)
3.현재 인덱스 (idx)
4.원본 배열 (src)
reduce() 메서드는 초기값을 주고 안주고에 따라 콜백의 실행 횟수가 차이가 난다. 초기값을 준다면 주지 않은 경우보다 1번 더 콜백이 실행된다.
예)
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
});
callback | accumulator | currentValue | currentIndex | array | 반환 값 |
---|---|---|---|---|---|
1번째 호출 | 0 | 1 | 1 | [0, 1, 2, 3, 4] | 1 |
2번째 호출 | 1 | 2 | 2 | [0, 1, 2, 3, 4] | 3 |
3번째 호출 | 3 | 3 | 3 | [0, 1, 2, 3, 4] | 6 |
4번째 호출 | 6 | 4 | 4 | [0, 1, 2, 3, 4] | 10 |
---> 반환 값은 10이 된다.
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
}, 10);
callback | accumulator | currentValue | currentIndex | array | 반환값 |
---|---|---|---|---|---|
1번째 호출 | 10 | 0 | 0 | [0, 1, 2, 3, 4] | 10 |
2번째 호출 | 10 | 1 | 1 | [0, 1, 2, 3, 4] | 11 |
3번째 호출 | 11 | 2 | 2 | [0, 1, 2, 3, 4] | 13 |
4번째 호출 | 13 | 3 | 3 | [0, 1, 2, 3, 4] | 16 |
5번째 호출 | 16 | 4 | 4 | [0, 1, 2, 3, 4] | 20 |
추가적으로 알면 좋은 reduce() 사용법
flatMap()메서드와 reduce() + concat() 메서드로 2차원 배열을 평탄화 할 수 있다.const arr = [ [1, 2], [3, 4], [5, 6], ]; // reduce와 concat 이용 const joinReduveArr = arr.reduce(function (acc, val) { return acc.concat(val); }); console.log(joinReduveArr); //flatMap 이용 const joinFlatMapArr = arr.flatMap((x) => x); console.log(joinFlatMapArr);
위 코드는 동일하게 [ 1, 2, 3, 4, 5, 6 ] 이 출력된다.
출처 및 참고 : https://developer.mozilla.org/ko/