함수형 프로그래밍 (functional programming)
프로그래밍하려는 문제를 함수 정의와 조합을 통해서 해결하려는 방법
함수의 개념을 최우선으로 사용해 모든 문제를 프로그래밍하는 프로그래밍 기법
로직 내에 존재하는 조건문 및 반복문을 제거해 복잡성을 해결, 변수의 사용을 억제해 상태 변경을 피하려는 프로그래밍
→ 순수 함수를 통해 부수 효과를 최대한 억제해 오류를 피하고 프로그램 안정성을 높이려는 방법
▷ 함수형 프로그래밍 특성
애플리케이션을 작성할 때 확장성, 모듈화, 재사용성, 테스트 용이성에 도움을 줄 수 있음
애플리케이션의 부수효과를 방지하고 상태 변이감소를 위해서 데이터의 제어 흐름 / 연산을 추상화
명령형 프로그래밍 vs 선언적(함수형) 프로그래밍
명령형 프로그래밍 "어떻게 구현하는가"
선언적 프로그래밍 "무엇을 나타내야 하는가"
함수형 프로그래밍은 선언적 프로그래밍 패러다임에 속함
명령형 프로그램은 어떤 결과를 내기 위해서 시스템의 상태를 변경하는 구문을 위에서 아래로 늘어놓은 순열에 불과
선언적 프로그램은 명령형으로 작성된 코드를 함수로 추상화 (순수함수 사용, 불변성)
서술부 + 평가부 분리를 통해 제어 흐름 OR 상태 변화를 특정하지 않아도 프로그램 로직이 무엇인지 표현식으로 나타냄
// 명령형 "어떻게" 처리하는지에 대한 묘사
function d(arr) {
let r = [];
for (let i = 0; i< arr.length; i++) {
if(typeof arr[i] === 'number'){
res.push(arr[i] * 2)
}
}
return r
}
// 선언형 "무엇을" 원하는지에 대한 묘사
// 배열 작업을 하나하나 끊는 형태로 표현하기 때문에, 가능하지만 매력적임
fucntion d(arr) {
return arr
.filter(param => typeof param === `number`)
.map(number => number *2)
}
▷ 순수함수
주어진 입력에만 의존해 평가 도중 변경될 수 있는 숨겨진 값이나 외부 상태와 무관하게 동작함,
전역 객체나 레퍼런스로 전달된 매개변수를 수정하는 등 함수 스코프 밖에서 어떠한 변경도 일으키지 않는 함수
상태 변이를 줄이고 관리할 수 있는 프레임워크를 제공해 순수/불순 함수를 구분
(함수가 일관된 반환 값을 보장하도록 해, 함수 결과를 예측 가능한 방향으로 유도하는 것)
- 순수 함수를 사용한 코드는 전역 상태를 바꾸거나 깨뜨릴 일이 없어, 테스트 및 유지 보수가 더욱 더 쉬운 코드 개발가능
컬렉션 데이터는 MAP, REDUCE를 작성해 함수 체인으로 연결해 매끄럽게 처리할 수 있도록 함
고차(고계) 함수 higher - order - function
다른 함수에서 작동하는 함수를 인수로 사용/반환 (객체지향 + 함수형)
인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성해 반환함 (일급객체 특성)
외부 상태의 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 둠
function makeCount(p) {
// 자유 변수 : num의 상태는 유지되어야 함
let num = 0;
// 클로저 : num의 상태를 유지
return function() {
//p함수는 자유 변수인 num의 상태를 변화
num = p(num);
return num;
};
}
// 보조 함수
funcrion increase(n) {
return ++n;
}
// 보조 함수
function decrease(n) {
return --n;
}
// makeCount는 함수를 인수로 전달받음, 클로저를 반환
const Increase = makeCount(increase);
console.log(Increase()); // -1
함수의 부분 적용 Partial Applied function
n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨서 기억함
나중에 (n-m)개의 인자를 넘기면 원래 함수의 실행 결과를 얻을 수 있게끔 하는 함수
→ 미리 일부 인자를 넘겨두어서, 추후 필요한 시점에 기억했던 인자들까지 함께 실행하고 싶은 경우
▷ bind 함수
객체 메서드를 콜백으로 전달할 때, this 정보가 사라지는 문제점이 생김 (객체 내부가 아닌 다른 곳에 전달되면 사라짐)
this를 수정하게 해 주는 내장 메서드 bind를 제공하는데, func.bind는 함수처럼 호출 가능한 특수 객체를 반환함
- bind는 컨텍스트를 this로 고정할 뿐만 아니라, 함수의 인수도 고정함 ( 추가된 인수도 그대로 전달)
// 부분 적용을 사용하면 기존 함수의 매개변수를 고정해 새로운 함수를 만들 수 있음
function mul(a,b) {
return a*b;
}
let double = mul.bind(null,2);
alert(double(3)); // = mul(2,3) = 6
메모이제이션 Memoization
비용이 많이 드는 함수(expensive function calls) 호출의 결과를 저장하고
동일한 입력이 다시 발생할 때, 캐시된 결과를 반환하여 애플리케이션 속도를 높이는 최적화 기술
실행시간이 줄어들긴 하지만, 메모리를 버리기 때문에, 입력 범위가 제한된 함수에 사용
(함수 연산의 결과 값이 제곱근과 같이 확실하게 고정된 값인 경우에 사용)
▷ 비용이 많이 드는 함수?
함수 호출을 실행하는데 소비되는 시간과 자원(메모리)의 양이 많다는 것
이러한 비용을 줄인다면, 함수를 빠르고 쉽게 엑세스 할 수 있게 됨
▷ 캐시 (cash)
해당 데이터에 대해 요청이 들어왔을 때, 빠르게 처리될 수 있도록 데이터를 보관하는 임시 데이터 저장소
캐시에 저장된 이후 애플리케이션 내에서 함수가 다시 호출될 때 마다 계산을 다시 실행하지 않고 결과가 빠르게 반환됨
▷ 메모이제이션 동작 예시 ( Closure / Higher Order Functions )
// 제시된 함수
function sqrt(arg) {
return Math.sqrt(arg);
}
log(sqrt(4)) // 2
log(sqrt(9)) // 3
// 제시된 함수를 메모이제이션을 이용해 작성
function sqrt(arg) {
//sqrt 함수에 cache라는 프로퍼티가 없다면 빈 객체 지정
if (!sqrt.cache) {
sqrt.cache = {}
}
// sqrt 함수의 메모이제이션 값이 없다면
if (!sqrt.cache[arg]) {
return sqrt.cache[arg] = Math.sqrt(arg)
}
// sqrt 함수의 메모이제이션 된 값이 있다면 연산하지 않고 값을 리턴
return sqrt.cache[arg]
}
참고자료 https://ko.javascript.info/bind
'JAVASCRIPT' 카테고리의 다른 글
[자바스크립트] reduce() / reduceRight() (0) | 2022.09.21 |
---|---|
[자바스크립트] 실행 컨텍스트 (0) | 2022.09.19 |
[자바스크립트] bind() (1) | 2022.09.19 |
[자바스크립트] 함수 호출 (1) | 2022.09.19 |
[자바스크립트] 중첩함수 (0) | 2022.09.17 |