curring 패턴
커링패턴
함수를 설계할 때 인자 전체를 넘겨서 호출할 수 도 있지만, 일부 인자는 먼저 입력해두고 나머지만 입력받을 수 있도록 새로운 함수를 만드는 패턴을 의미한다.
특히 자바스크립트에서 클로저가 있어서 먼저 일부 입력된 값을 유지하고, 가지고 있는 것을 아주 쉽게 구현할 수 있기 때문에 유용하게 사용할 수 있는 패턴이다.
(function(){ function sum(x, y){ return x + y; } var makeAdder = function(x){ return function(y){ return sum(x,y); }; }; var adderFour = makeAdder(4); console.log(adderFour(1)); //5 console.log(adderFour(5)); //9 }()); |
더하기 함수는 x와 y 두개의 인자를 받는다.
그런데 커링 패턴을 적용하면 사전에 x인자는 입력해두고, 별도의 함수를 생성하여 y만 입력하면 자동으로 x를 더하게 할 수 있다.
makeAdder()함수로 인자를 하나 받은뒤, 나머지 인자를 하나 받는 함수를 반환한다.
여기서 반환된 함수가 호출되면 클로저로 저장되어 있던 x 와 새로 입력되어 들어온 y를 sum() 함수의 인자로 넘긴다.
그 결과 x의 값을 4을 먼저 고정하고 이후 y만 입력하더라도 sum(x, y)의 결과가 나온다.
(function(){ Function.prototype.curry = function(){ if(arguments.length < 1){ return this; } var _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; } var 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; } var adderCurry = sum4.curry(5, 1); console.log(adderCurry(2, 3)); //11 }()); |
sum()함수의 인자를 여러 개를 동적으로 받으면서 Function.prototype에 추가해서 기존 함수들이 쉽게 커링 패턴을 적용할 수 있다.
sum4() 함수는 4개의 인자를 받고 있으며, curry()함수에는 5,1 두개의 인자를 먼저 적용해놓았다.
여기서 추가로 2와 3을 인자로 넘겨 주면 총합 11이 반환되는 것을 확인할 수 있다.
이처럼 자바스크립트는 arguments 객체와 apply() 함수로 가변 인자들을 유동적으로 변경하고 클로저를 통해 먼저 넘어온 데이터 값에 대한 보관까지 쉽게 할 수 있다.
(function(){ Function.prototype.curry = function(){ if(arguments.length<1){ return this; } var _this = this, args = Array.prototype.slice.apply(arguments); return function(){ console.log(arguments); 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}`; } var cm2inch = unitConvert.curry('cm','inch',0.393701), metersquqre2pyoung = 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); console.log(cm2inch(10)); console.log(metersquqre2pyoung(30)); console.log(kg2lb(50)); console.log(kmph2mph(100)); }()); |
unitConvert() 함수에서 변환할 단위들을 받고 변환될 계수를 먼저 인자로 받은 다음, 나중에 input만 받도록 하고 있다.
특수 목적의 함수가 아니라 일반적인 웹페이지에서 사용할 수 있는 함수라면 앞서 잠깐 사용했던 ajax()함수를 커링 패턴으로 조금 변경할 수 있다.
(function(){ Function.prototype.curry = function(){ if(arguments.length<1){ return this; } var _this = this, args = Array.prototype.slice.apply(arguments); return function(){ console.log(arguments); return _this.apply(this, args.concat(Array.prototype.slice.apply(arguments))); } } function ajax(method, url, data, callback){ var xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.onload = function(){ if(xhr.status === 200){ callback.call(this, xhr.responseText); } } xhr.send(data); } var ajaxGet = ajax.curry("GET"), ajaxPost = ajax.curry("POST"), ajaxPut = ajax.curry("PUT"), ajaxDelete = ajax.curry("DELETE"); ajaxGet("/data", null, function(responseText){ console.log(responseText); }); }()); |
REST API에서 자주 사용하는 XMLHttpRequest의 4가지 메소드에 대해서 별도의 ajax()함수로 정의하여 사용할 수 있다.
이러한 방식은 이미 jQuery 라이브러리에서도 사용하는 방식으로 순수 자바스크립트만으로 쉽게 구현할 수 있다.
이처럼 커링 패턴은 자바스크립트의 언어적 특징 때문에 아주쉽게 구현할 수 있으며, 인자가 많은 공통 라이브러리를 사용할 때 유용하게 활용할 수 있다는 장점이 있다.
하지만 클로저도 그렇지만 프로그램이 돌아가는 순서를 쫓아가기에는 조금 힘들수 도 있다는 단점도 있으니 개발 효율성과 소스 관리에 대한 균형을 잘 맞춰야 한다.
출처-속깊은 자바스크립트 양성익 지음
'FRONT-END > JAVASCRIPT' 카테고리의 다른 글
자바스크립트 레이지로드(lazy load) (1) | 2018.01.08 |
---|---|
자바스크립트 디자인 패턴 #정리 (0) | 2018.01.05 |
자바스크립트 디자인 패턴 #9. Callback Function 패턴 (0) | 2018.01.05 |
자바스크립트 디자인 패턴 #8. Self-invoking constructor 패턴 (0) | 2018.01.03 |
자바스크립트 디자인 패턴 #7. Memoization 패턴 (0) | 2018.01.03 |