순수 함수 란 똑같은 인자들을 함수의 인자에 넣었을 때 항상 똑같은 결괏값을 리턴하는 함수이다.
또한 부수 효과(side effect)가 없다. 여기서 부수 효과가 무엇일까 ?
부수효과 란 함수 내부와 외부가 서로 상호작용 하는 것을 말한다. 예를 들면, 함수 내부에서 함수 외부에 있는 변수의 값을 재할당한다거나 외부의 함수를 함수 내부에서 호출하는 것이다.
const temp_num = 5;
function sum (a, b) {
return a + b + temp_num;
}
위의 함수는 같은 인자가 들어왔을 때 항상 같은 값을 리턴하기에 순수 함수가 맞을까 ?
정답은 아니다. 함수 내부에서 함수 외부의 변수에 의존하기 때문이다.
또 다른 예시를 보면
const me = {
name: "맹구",
hobby: "돌 줍기",
canSmile: true
}
function change () {
me.canSmile = false;
return me;
}
change();
위의 함수도 항상 똑같은 값을 리턴 할 것이다.
그러나 이 함수는 인자를 받지도 않으며, 함수 외부의 me 라는 객체의 프로퍼티의 값을 재할당 하기에 순수함수라고 볼 수 없다.
function sum_2(num) {
return num * 2;
}
위의 함수는 순수 함수일까 ?
정답은 맞다. 함수가 외부의 input에 의존하지도 않고, 어떠한 데이터도 변하게 하지 않는다. 고로 부수 효과가 존재하지 않는 순수 함수이다. 또한 같은 인자가 들어왔을 때 항상 같은 값을 리턴하기도 한다.
const multiply_random_number = (num) => Math.random() * num;
multiply_random_number(10);
위의 함수는 순수 함수가 아니다. 매 실행시마다 다른 결과 값을 리턴하기 때문이다.
순수함수는 인자를 변경 불가능한 데이터로 취급한다.
자바스크립트에서 객체, 배열, 함수는 참조형 자료이다. 참조형 자료는 변수에 값이 아닌 자료가 담겨져 있는 곳의 주소값을 담는다.
let a = [1, 2];
let b = a;
a.push(3);
console.log(a); // [1, 2, 3];
console.log(b); // [1, 2, 3];
만약 다른 곳에서 객체의 프로퍼티나 배열의 원소들을 바꾼다면 원본도 바뀐다. 이에 따라, 순수 함수의 성질에 반하게 된다. 그렇다면 어떻게 해야 할까 ?
정답은 바로 불변성이다. 불변성은 변하지 않는다는 의미를 내포하고 있다. 즉, 데이터를 변하지 않게 만드는 것이다. 그렇다면 인자에 들어온 객체나 배열의 원본 데이터를 변경하지 않고 안전하게 사용하려면 어떻게 해야 할까 ?
const color = ["red", "cornflower blue", "black"];
function addColor (color_array, color_string) {
return color_array.concat(color);
}
addColor(color, "white") // ["red", "cornflower blue", "black", "white"]
console.log(color) // ["red", "cornflower blue", "black"];
const myDog = {
name: "멍멍이",
canFight: false,
cry: true
}
function dog_military (dog) {
return Object.assign({}, dog, { canFight: true })
}
dog_military(myDog)
/* {
name: "멍멍이",
canFight: true,
cry: true
} */
console.log(myDog)
/*
{
name: "멍멍이",
canFight: false,
cry: true
}
*/
// Array
const color = ["red", "cornflower blue", "black"];
function addColor (color_array, color_string) {
return [...color_array, color_string];
}
addColor(color, "white") // ["red", "cornflower blue", "black", "white"]
console.log(color) // ["red", "cornflower blue", "black"];
// Object
const myDog = {
name: "멍멍이",
canFight: false,
cry: true
}
function dog_military (dog_array) {
return { ...dog_array, canFight: true };
}
dog_military(myDog)
/* {
name: "멍멍이",
canFight: true,
cry: true
} */
console.log(myDog)
/*
{
name: "멍멍이",
canFight: false,
cry: true
}
*/