코린이의 기록

[ES6] 함수와 추상적 사고 본문

javascript,HTML,CSS

[ES6] 함수와 추상적 사고

코린이예요 2019. 7. 30. 18:46
반응형

서브루틴으로서의 함수

함수의 가장 간단한 사용 형태를 강조하기 위해서 서브루틴이라는 용어를 씀. 

예제 

function printLeapYearStatus() {
    const year = new Date().getFullYear();
    if(year % 4 !== 0) console.log(`${year} IS NOT a leap year`);
    else if(year % 100 !== 0) console.log(`${year} IS a leap year.`);
    else if(year % 400 !== 0) console.log(`${year} is NOT a leap year.`);
    else console.log(`${year} IS a leap year`);
}
printLeapYearStatus();

Result

위 예제는 올해가 윤년인지 확인하는 함수이다. 여기서 함수의 이름은 printLeapYearStatus라고 지정했는데 이는 오늘이 윤년인지 console에서 print한다는 의미를 가지고 있다. 함수 이름을 leapYearStatus나 leapYear라고 지정하지 않는 이유는 이 함수의 기능이 윤년인지를 판단하여 콘솔에 출력하기까지의 기능을 나타내기 때문이다. 

값을 반환하는 서브루틴으로서의 함수

예제

function isCurrentYearLeapYear(){
    const year = new Date().getFullYear();
    if(year % 4 !==0) return false;
    else if(year % 100 != 0) return true;
    else if (year % 400 != 0) return false;
    else return true;
}
console.log(isCurrentYearLeapYear());

Result

위 예제는 오늘이 단지 윤년인지 아닌지에 대해 값을 반환하는 함수이다. 이때 불리언으로 반환하는 경우 함수는 is로 시작하는 이름을 붙이는것이 일반적이다. 

함수로서의 함수

입력이 들어가면 결과가 나오는 함수, 즉 수학적인 정의에 충실한 함수를 순수한 함수라고 부른다. 여기서 순수한 함수의 특징은 입력이 같으면 결과도 반드시 같다라는 점이다. 위에서 isCurrentYearLeapYear()함수에서는 언제 호출하느냐에 따라서 반환되는 값이 달라진다. 그러면 위 예제를 순수한 함수로 바꿔보자

function isLeapYear(year){
    if(year % 4 !==0) return false;
    else if(year % 100 !=0 ) return true;
    else if(year % 400 !=0 ) return false;
    else return true;
}

입력이 같으면 결과가 항상 같은 값이 나온다. 

 

IIFE(Immediately Invoked Function Expressions)와 비동기적 코드

IIFE는 즉시 호출하는 함수이다. 아래는 IIFE 예제로 카운트다운을 실행한다. 

참고로 setTimeout함수는 일정 시간 후에 특정 코드, 함수를 의도적으로 지연한 뒤 실행하고 싶을 때 사용하는 함수이다. 보통 두개의 인자를 갖는데, function과 interval time(miliseconds)이다. 여기서 function은 interval time이 지날때 콜백으로 호출되는 함수이다. 

var i;
for(i=5; i>=0; i--){
    setTimeout(function() {
        console.log(i===0 ? "go!" : i);
    }, (5-i)*1000);
}

위 예제의 결과를 예상해보자.

Result

...더보기

-1

-1

-1

-1

-1

-1

예상했던 답이 

5 4 3 2 1 go! 였는데 답은 달랐다. 각 줄에 console로 print 해보았다. 

var i;
for(i=5; i>=0; i--){
    console.log( "inside for loop i : " + i);
    setTimeout(function() {
        console.log(i===0 ? "go!" : i);
    }, (5-i)*1000);
}

Result

즉 setTimeout은 루프안에서 실행되지 않고 루프가 종료된 후에 실행되기 때문이다. 

위 문제를 블록 스코프 변수를 사용하여 해결할 수 있다. 

해결 방법

...더보기

for(let i=5; i>=0; i--){

setTimeout(function() {

console.log(i===0 ? "go!" : i);

}, (5-i)*1000);

}

변수로서의 함수

함수를 변수로서 별명을 지어서 사용할 수 있다. 

아래 예제는 3개의 square를 

function addThreeSquareAddFiveTakeSqaureRoot(x) {
    return Math.sqrt(Math.pow(x + 3, 2) + 5);
}

const answer = (addThreeSquareAddFiveTakeSqaureRoot(5) +
    addThreeSquareAddFiveTakeSqaureRoot(2)) / addThreeSquareAddFiveTakeSqaureRoot(7);

console.log("answer : " + answer);
const f = addThreeSquareAddFiveTakeSqaureRoot;
const answer2 = (f(5) + f(2)) / f(7);

console.log("answer2 : " + answer2);

여기서 f = addThreeSquareAddFiveTakeSqaureRoot에 괄호를 붙이는 실수는 하지 않도록 한다. 괄호를 붙이면 함수를 호출하게 된다. 괄호를 붙이지 않아야 addThreeSquareAddFiveTakeSqaureRoot 함수의 결과 값을 저장하게 된다.

Result

배열안에서의 함수

배열안에서의 함수는 파이프라인(한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조)으로 사용하기 좋다. 다음은 2차원 그래픽 변형을 위한 예제이다. 시각화 소프트웨어를 만들 때 파이프라인으로 묶어서 적용할때가 많다. 

const sin = Math.sin;
const cos = Math.cos;
const theta = Math.PI/4;
const zoom = 2;
const offset = [1, -3];

const pipeline = [
    function rotate(p) {
        return {
            x: p.x * cos(theta) - p.y * sin(theta),
            y: p.x * sin(theta) + p.y * cos(theta),
        };
    },
    function scale(p) {
        return {x:p.x * zoom, y:p.y*zoom};
    },
    function translate(p) {
        return {x:p.x + offset[0], y:p.y + offset[1]};
    }
];

const p = {x : 1, y: 1};
let p2 = p;
for(let i=0; i<pipeline.length; i++){
    p2 = pipeline[i](p2);
}

console.log("p2 : " + JSON.stringify(p2));

Result

p2 : {"x":1.0000000000000002,"y":-0.17157287525381015}

함수를 반환하는 함수

말그대로 함수에서 함수를 반환하기도 한다. 

예제

function sum(arr, f){
    if (typeof f != 'function') f = x => x;
    return arr.reduce((a,x) => a+= f(x), 0);
}
function sumOfSqares(arr){
    return sum(arr, x => x*x);
}

console.log(sumOfSqares([1,2,3]));

Result 

14

 

 

 

Reference : Learning Javascript (이선 브라운 지음)

반응형
Comments