함수의 목적
- 매핑(mapping): 입력값에 기반하여 결과값을 리턴한다. 컴퓨터 세계에서는 "입력 값을 출력 값에 매핑한다"라고 말한다.
- 프러시저(procedure, 절차): 함수는 일련의 과정을 수행하기 위해 실행된다. 이 일련의 과정을 우리는 프로시저라고 부른다. 또한, 이러한 스타일로 프로그래밍하는 것을 절차형 프로그래밍(procedural programming)이라고 한다.
- I/O(입출력): 스크린, 저장소, 시스템 로그나 네트워크 등과 대화하기 위해 함수를 사용할 수도 있다.
1) 입력한 값을 가공한 결과값이 필요할 때
2) 이 결과값으로 여러 과정을 거쳐야 할 때
3) 다른 시스템과 정보를 주고받기 위해 사용한다.
순수 함수와 비순수 함수
순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환하는 함수다. 즉, 순수 함수는 어떤 외부 상태에도 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에게만 의존해 값을 생성해 반환한다.
외부 상태에는 전역 변수, 서버 데이터, 파일, Console, DOM 등이 있다.
만약 외부 상태에는 의존하지 않고 함수 내부 상태에만 의존한다 해도 그 내부 상태가 호출될 때마다 변화하는 값(ex: 현재 시간)이라면 순수 함수가 아니다.
순수 함수는 일반적으로 최소 하나 이상의 인수를 전달받는다. 인수를 전달받지 않는 순수 함수는 언제나 동일한 값을 반환하므로 결국 상수와 마찬가지기 때문에 그다지 의미가 없다. 또한 순수 함수는 인수를 변경하지 않는, 인수의 불변성을 유지한다.
순수함수
순수 함수의 또 하나의 특징은 함수의 외부 상태를 변경하지 않는다는 것이다. 즉, 순수 함수는 어떤 외부 상태에도 의존하지 않으며 외부 상태를 변경하지도 않는 함수다.
- 같은 입력값이 주어졌을 때, 언제나 같은 결괏값을 리턴한다.
- 사이드 이펙트를 만들지 않는다. (= 외부에서 선언된 상태(state)를 수정하지 않는다.)
var count = 0; // 현재 카운트를 나타내는 상태
// 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환한다.
function increase(n) {
return ++n;
}
// 순수 함수가 반환한 결과값을 변수에 재할당해서 상태를 변경
count = increase(count);
console.log(count); // 1
count = increase(count);
console.log(count); // 2
순수 함수는 사이드 이펙트를 만들지 않는다
순수 함수는 사이드 이펙트를 만들지 않는다, 순수 함수는 외부 상태를 바꿀 수 없다.
불변성
자바스크립트의 객체, 배열, 함수는 참조 타입(reference type)이다. 참조 타입은 그 값이 저장되는 것이 아니라, 그 값을 저장하고 있는 주소를 담고 있다.
만약 어떤 객체(또는 다른 참조타입)를 함수의 인자로 보내고, 함수 안에서 인자로 주어진 객체의 내용을 변경하면, 원본 객체도 그 값이 변하게 된다.
다시 말해, 외부에서 정의된 참조 타입을 함수 내부에서 변경시키는 것이다.
function addFemale(book, customer, quantity) {
book.push({
customer,
quantity,
});
return book;
}
const bookingObj = {};
const obj = addFemale(bookingObj, { name: "youjin", age: 25 }, 1);
console.log(obj === bookingObj); // true
bookingObj는 전역에서 정의된 객체이다. 그리고 addFemale() 함수에 해당 객체를 인자로 넘겨, 객체 내에 값을 추가하고 그대로 리턴해주었다. 함수가 인자로 받은 객체는 원본 객체이기 때문에, 해당 객체를 조작하는 것은 외부에서 선언된 객체를 조작하는 것이 된다.
순수 함수의 두번째 조건은 외부 함수를 바꾸지 않는 것(= 사이드 이펙트를 만들지 않는 것)이다.
그러나 bookingObj는 외부에서 선언된 객체를 조작하였으므로 순수하지 않은 함수라고 볼 수 있다.
bookingObj 함수를 순수하게 만들려면 어떻게 해야 할까? 일단, 함수에 인자로 주어진 객체를 직접 조작하면 안 된다!
function addFemale(book, customer, quantity) {
const newBook = { ...book }; // 원본 객체를 얕게 복사
newBook.push({
// 복사된 객체를 조작
customer,
quantity,
});
return newBook; // 복사된 객체를 리턴
}
const bookingObj = {};
const obj = addFemale(bookingObj, { name: "youjin", age: 25 }, 1);
console.log(obj === bookingObj); // true
위의 예제에서는 함수의 인자로 받은 객체를 얕게 복사하고, 원본 객체를 조작하는 대신 복사한 객체를 조작하고 리턴하였다.
수정한 예제에서는 함수 내에서 원본 객체가 변하지 않았기 때문에 사이드 이펙트가 발생하지 않았다.
의도한 대로 함수의 인자에 대한 결과값을 얻어냈다.따라서 수정한 addFemale 함수는 순수 함수의 조건을 만족한다.
- 순수 함수는 실행 시점이 중요하지 않다.
순수 함수가 가지는 가장 큰 매력은 바로 실행되는 시점과 상관없이 항상 동일한 결과를 만들어내는 것이다. 예제 코드를 통해 보여드린 순수 함수는 누가 언제 실행시키든 항상 동일한 기능을 수행한다. 다르게 말하면 멀티스레드 환경에서든 비동기적인 상황에서든 언제나 안전하게 믿고 사용할 수 있다. 반면 순수하지 않은 함수는 어떤가요? 외부에 정의되어 있는 요소에 따라 결과가 판이하게 바뀌기 때문에 어떤 결과를 만들어 낼지 예측이 불가능하다.
- 순수 함수는 조합성을 높여준다.
순수 함수는 예측이 가능한 결과를 반환하기 때문에 다른 순수 함수들과 조합해서 사용하기가 용이하다. 즉 재사용성이 좋다고 말할 수 있고 대체적으로 하나의 기능에 충실하기 때문에 응집도가 매우 높아 유지보수가 편리한 부분도 있다.
비순수 함수
반대로 함수의 외부 상태에 따라 반환값이 달라지며 상태에 의존하는 함수를 비순수 함수라고 한다. 비순수 함수의 또 하나의 특징은 함수의 외부 상태를 변경하는 부수 효과가 있다는 것이다. 즉, 비순수 함수는 외부 상태에 의존하거나 외부 상태를 변경하는 함수다.
var count = 0;
// 비순수 함수
function increase() {
return ++count; // 외부 상태에 의존하며 외부 상태를 변경한다.
}
// 비순수 함수는 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려워진다.
increase();
console.log(count); // 1
increase();
console.log(count); // 2
비순수 함수 문제점
공유 상태(Shared state)로 인한 문제
입력값(=인자)이 일관적이지 않고 예측할 수 없는 값이라면 (일관적이지 않은 요소(indeterministic factor))
함수의 결과값을 예측할 수 없다.
일관적이지 않은 요소는 의도에 따른 결과값을 예측할 수 없게 만든다. 결과값을 예측할 수 없는 함수는 자기가 만든
함수임에도 함수를 실행하면 어떤 값이 나올지 예측할 수 없다. 이 함수를 테스트하거나, 온전히 이해할 수 없는 것이다
병렬 처리(parallel processing)와 비결정성 이슈
스칼라의 창시자 Martin Odersky는 다음과 같이 말했다.
비결정성(non-determinism) = 병렬 처리(parallel processing) + 변이 할 수 있는 상태(mutable state)
자바스크립트가 싱글 스레드로 동작하기 때문에 병렬 처리 관련 이슈는 없을 거라고 생각할 수도 있겠지만... 자바스크립트는 생각보다 많은 동시성 자원(parallel resources)을 가지고 있다. AJAX, API I/O, 이벤트 리스너, iframes, timeout 등은
프로그램에 비결정성 이슈를 만들어낼 수 있다.
출처:https://velog.io/@nittre/JavaScriptFunction-Composition-Series-1.-Pure-Function
https://7942yongdae.tistory.com/143
참고하면 좋은 강의
정리: 순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환하는 함수를 뜻 합니다. 순수 함수는 어떤 외부 상태에도 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에게만 의존해 값을 생성해 반환한다.
자바스크립트의 객체, 배열, 함수는 참조 타입인데요. 참조 타입은 그 값이 저장되는 것이 아니라, 그 값을 저장하고 있는 주소를 담고 있습니다.
만약 어떤 객체(또는 다른 참조타입)를 함수의 인자로 보내고, 함수 안에서 인자로 주어진 객체의 내용을 변경하면, 원본 객체도 외부에서 정의된 참조 타입을 함수 내부에서 변경시키게 되는데요 .
이렇게 순수함수를 생성시에는 참조값의 원본을 조작하지 않고 불변성을 주의하며 함수를 생성해야 합니다.
'javascript' 카테고리의 다른 글
constructor 와 non-constructor (0) | 2023.04.23 |
---|---|
생성자 함수 (0) | 2023.04.20 |
require와 import (1) | 2023.02.27 |
parameter 와 argument(인수, 인자) (0) | 2023.02.22 |
비동기와 Promise (0) | 2022.12.13 |