본문 바로가기
Study Note/Javascript

javascript #디자인 패턴 - 커링 패턴(currying pattern)

by 시뮝 2021. 2. 13.
728x90

커링 패턴

커링(currying) 패턴은 함수를 설계할 때 인자 전체를 넘겨서 호출할 수도 있지만, 일부 인자는 먼저 입력해두고 나머지만 입력받을 수 있도록 새로운 함수를 만드는 패턴을 의미합니다. 커링 패턴은 하나의 공용 함수가 있는 경우 이를 세부적인 기능을 하는 함수로 나누고 싶을 때 유용합니다.

 

적용예시1. 합을 구하는 기본 함수

makeAdder() 함수로 인자를 하나 받은 뒤, 나머지 인자를 하나 받는 함수를 반환한다. 여기서 반환된 함수가 호출되면 클로저로 저장되어 있던 x와 새로 입력되어 들어온 y를 sum()  함수의 인자로 넘긴다. 그 결과 sum(x,y)의 결과가 나온다.

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div id="userInfo"></div>
        <script>
        (function () {
            function sum(x, y) {
                return x + y;
            }
            
            let makeAdder = function (x) {
                return function (y) {
                    return sum(x, y);
                };
            };
            
            console.info("커링 패턴 적용 X")
            console.log(sum(4,1)); // === 5
            console.log(sum(4,5)); // === 9
            
            console.info("커링 패턴 적용 O")
            let adderFour = makeAdder(4);
            console.log(adderFour(1)); // === 5
            console.log(adderFour(5)); // === 9
        }());
        </script>
    </body>
</html>

 

적용예시2. Function.prototype에 커링 패턴 함수 추가

자바스크립트는auguments 객체와 apply() 함수로 가변 인자들을 유동적으로 변경하고 클로저를 통해 먼저 넘어온 데이터 값에 대한 보관까지 쉽게 할 수 있어 아래와 같이 구현할 수 있습니다.

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div id="userInfo"></div>
        <script>
        (function () {
            Function.prototype.curry = function() {
                if (arguments.length<1) {
                    return this;
                }
                let _this = this,
                    args = Array.prototype.slice.apply(arguments);
                return function() {
                    return _this.apply(this, args.concat(Array.prototype.slice.apply(arguments)));
                }
            }
            
            function sum(x, y) {
                return x + y;
            }
            
            let adderFourCurry = sum.curry(4);
            console.log(adderFourCurry(5)); // === 9
            console.log(adderFourCurry(10)); // === 14
            
            function sum4(x, y, z, w) {
                return x + y + z + w;
            }
            
            let adderCurry = sum4.curry(5,1);
            console.log(adderCurry(2,3)); // === 11
        }());
        </script>
    </body>
</html>

 

적용예시3. 커링 패턴을 이용한 단위 변환

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div id="userInfo"></div>
        <script>
        (function () {
            Function.prototype.curry = function() {
                if (arguments.length<1) {
                    return this;
                }
                let _this = this,
                    args = Array.prototype.slice.apply(arguments);
                return function() {
                    return _this.apply(this, args.concat(Array.prototype.slice.apply(arguments)));
                }
            }
            
            function unitConvert(fromUnit, toUnit, factor, input)  {
                return `${input} ${fromUnit} === ${(input*factor).toFixed(2)} ${toUnit}`;
            }
            
            let cm2inch = unitConvert.curry('cm', 'inch', 0.393701),
                metersquare2pyoung = unitConvert.curry('m^2', 'pyoung', 0.3025),
                kg2lb = unitConvert.curry('kg', 'lb', 2.204623),
                kmph2mph = unitConvert.curry('km/h', 'mph', 0.621371);
            
            console.log(cm2inch(10));
            console.log(metersquare2pyoung(30));
            console.log(kg2lb(50));
            console.log(kmph2mph(100));
            //==>> 
            // 10 cm === 3.94 inch
            // 30 m^2 === 9.07 pyoung
            // 50 kg === 110.23 lb
            // 100 km/h === 62.14 mph
        }());
        </script>
    </body>
</html>

 

적용예시4. XMLHttpRequest를 위한 커링 패턴 응용

 

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div id="userInfo"></div>
        <script>
        (function () {
            Function.prototype.curry = function() {
                if (arguments.length<1) {
                    return this;
                }
                let _this = this,
                    args = Array.prototype.slice.apply(arguments);
                return function() {
                    return _this.apply(this, args.concat(Array.prototype.slice.apply(arguments)));
                }
            }
            
            function ajax(method, url, data, callback) {
                let xhr = new XMLHttpRequest();
                xhr.open(method, url);
                xhr.onload = function () {
                    if (xhr.status === 200) {
                        callback.call(this, xhr.responseText);
                    }
                }
                xhr.send(data);
            }
            
            let ajaxGet = ajax.curry("GET"),
                ajaxPost = ajax.curry("POST"),
                ajaxPut = ajax.curry("PUT"),
                ajaxDelete = ajax.curry("DELETE");
            
            ajaxGet("/data", null, function (responseText) {
                console.log(responseText);
            });
        }());
        </script>
    </body>
</html>

 

#

참고도서 : 속깊은 자바스크립트

이전글 : 

2021/02/10 - [Study Note/Javascript] - javascript #디자인패턴 - 폼 검증을 위한 데커레이터 패턴(decorator pattern)

 

javascript #디자인패턴 - 폼 검증을 위한 데커레이터 패턴(decorator pattern)

데커레이터 패턴 프락시 패턴은 호출되는 객체가 아닌 별도의 중간자 역할을 수행하는 프락시 객체가 추가 기능을 수행하는 패턴이라고 한다면, 데커레이터(decorator) 패턴은 호출 대상이 되는

simuing.tistory.com

2021/02/10 - [Study Note/Javascript] - javascript #디자인패턴 - 객체 기반 데커레이터 패턴(decorator pattern)

 

javascript #디자인패턴 - 객체 기반 데커레이터 패턴(decorator pattern)

하나의 객체에 여러 가지 기능들을 추가함으로써 기존의 객체에 추가로 꾸며진 객체를 만들어낼 수 있습니다. 데커레이터 패턴을 이용해 각기 다른 부품으로 이루어진 컴퓨터의 가격을 알아봅

simuing.tistory.com

2021/02/10 - [Study Note/Javascript] - javascript #디자인패턴 - 함수 기반 데커레이터 패턴(decorator pattern)

 

javascript #디자인패턴 - 함수 기반 데커레이터 패턴(decorator pattern)

프락시 패턴에서 살펴봤던 래퍼 기능을 데커레이터 패턴과 함께 사용하면, 해당 함수가 호출되기 전에 여러 가지 함수가 호출될 수 있도록 응용할 수 있습니다. 이렇게 응용할 수 있는 상황은

simuing.tistory.com

2021/02/10 - [Study Note/Javascript] - javascript #디자인패턴 - Init-time branching 패턴

 

javascript #디자인패턴 - Init-time branching 패턴

Init-time branching 패턴 Init-time branching 패턴은 이름 그대로 초기화 단계에서 분기하여 같은 함수를 환경에 따라 다르게 정의하는 것을 의미합니다. 보통 웹페이지가 처음 열릴 때 실행된다고 해서 I

simuing.tistory.com

2021/02/12 - [Study Note/Javascript] - javascript #디자인패턴 - Self-defining function 패턴

 

javascript #디자인패턴 - Self-defining function 패턴

Self-defining function 패턴 앞서 살펴본 Init-time branching 패턴은 처음 웹페이지 초기화 단계에서 컴퓨팅 자원을 소모하여 향후 어떠한 방법으로 함수가 호출될 지 결정하는 것이었다면, Self-defining funct

simuing.tistory.com

2021/02/13 - [Study Note/Javascript] - javascript #디자인패턴 - 메모이제이션 패턴 (memoization pattern)

 

javascript #디자인패턴 - 메모이제이션 패턴 (memoization pattern)

메모이제이션(memoization) 패턴 패턴의 이름대로 '메모'를 하는 것이 특징입니다. 메모를 하는 대상은 바로 함수 또는 객체입니다. 이 패턴의 활용 용도는 일반적인 프로그래밍 언어에서 캐시를 사

simuing.tistory.com

2021/02/13 - [Study Note/Javascript] - javascript #디자인패턴 - Self-invoking constructor 패턴

 

javascript #디자인패턴 - Self-invoking constructor 패턴

Self-invoking constructor 패턴 자바스크립트에서는 new 키워드를 생략하더라도 생성자 함수를 일반 함수인 것처럼 호출하고 실행하므로 오류는 발생하지 않고 오동작만 하게 됩니다. 이러한 경우는

simuing.tistory.com

2021/02/13 - [Study Note/Javascript] - javascript #디자인패턴 - 콜백 패턴(callback pattern)

 

javascript #디자인패턴 - 콜백 패턴(callback pattern)

콜백 패턴(callback pattern)  콜백 함수의 대표적인 사용처는 이벤트 핸들러이지만, 일반적인 자바스크립트 처리 로직 중에서도 이러한 콜백 패턴을 이용해서 해당 함수의 호출이 끝나고 난 뒤에

simuing.tistory.com

 

728x90

댓글