본문 바로가기
Web/Javascript

콜백, 모듈, 커링, 메모이제이션

by juein 2018. 2. 27.

11] 콜백

- 이름이 없어 호출하지 못하는 익명함수의 대표적인 용도가 콜백 함수다.


- 콜백함수는 코드를 통해 명시적으로 호출하는 함수가 아니라

어떠한 이벤트가 발생했을때, 특정 시점에 도달했을때 시스템에서 호출되는 함수다.


대체로 이벤트 핸들러가 콜백 함수로 등록되는 경우가 많다. (이벤트 핸들러는 'on + 이벤트명' 으로 지어져있다.)

//페이지 로드시 호출퇼 콜백함수
window.onload = function(){
  
  console.log('browser load~');
  
}
//버튼 클릭시 호출될 콜백함수
document.getElementById("test").onclick = function() {
  
  console.log('button click~');
  
};
//HTML
<button type="button" id="test">Test</button>

이벤트 핸들러가 아닌 콜백 함수의 예로는

var test_fn = function( num, cb ) {    // <- cb 매개변수는 콜백 함수를 받는 부분
  
  //if(typeof cb === 'function'){
  
    setTimeout(function() {
      var sum = 0;
      for( var i = 0; i <= num; i++ ){
        sum += i;
      }
      cb(sum);
  }, 1000); // 1초 뒤 실행  <- 0초후 실행으로 설정해도 비동기로 실행됨
    
  //}
  
};

test_fn( 10, function(result) {
  
  console.log('위에 있는 함수 실행의 결과 : ' + result); 
  
});

console.log('밑에 있는데도 먼저 실행된다~'); 

/*
console 출력 후
밑에 있는데도 먼저 실행된다~
위에 있는 함수 실행의 결과 : 55 
로 출력된다.
*/



12] 모듈

- 타 언어에서는 접근 제한자(public, private 등..) 이 있지만 자바스크립트에는 존재하지 않아

클로저와 스코프 개념을 통해서 접근제한자의 특징을 흉내낼 수 있다.


기본적인 모듈 패턴의 예로

var testModule_1 = (function(){
  
  var count = 0;

  return {
    inCounter : function(){  // <-- 클로저
      return ++count;
    }
  };

})();

//console.log( inCounter() ); //내부함수에 직접 접근 불가
console.log( '모듈 1의 inCount : ' + testModule_1.inCounter() ); // 1 출력
console.log( '모듈 1의 inCount : ' + testModule_1.inCounter() ); // 내부함수 count가 더해져 2 출력

var testModule_2 = (function(){
  
  var count = 10;
  
  return {
    inCounter : function(){
      return ++count;
    }
  };
  
})();

console.log( '모듈 2의 inCount : ' + testModule_2.inCounter() ); // 11 출력 
console.log( '모듈 2의 inCount : ' + testModule_2.inCounter() ); // 12 출력

// inCounter() 가 동일한 메서드 이름을 사용하지만 전혀 다른 스코프상에 존재하는 다른 값이다.

- 위 예제에서 testModule_1 or testModule_2 의 내부 리소스는 

해당 모듈 이름 testModule_1 or testModule_1를 통해서만 접근이 가능하다.


- 모듈에서 return 되지 않은 대상은 접근이 불가능하다.




13] 연속 호출(Cascade)

- 자바스크립트 에서 메소드의 반환값이 this 라면 연속 호출이 가능하다.

var number = function( val){
  
    this.value = val;
  
    this.plus = function(sum){
      this.value += sum;
      //console.dir(this);
      return this;
    };

    this.return= function(){
      return this.value;
    };
  
   return this;
  
}

//number 에 minus 기능을 하는 프로토타입 함수 추가
number.prototype.minus = function(min){  
    this.value -= min;
    //console.dir(this);
    return this;
}

console.log ( '결과 : ' + new number(10).plus(1).minus(2).return() );  // 10 + 1 - 2 : 9 출력


연속호출은 한번에 많은 작업을 할 수 있는 이너페이스를 만드는데 도움이 된다.




14] 커링(Curry)

- 커링이란 특정 함수에서 정의된 인자의 일부를 넣어 고정시키고, 나머지를 인자로 받는 새로운 함수를 만드는 것을 말한다.

var calculate = function( a, b, c ){
  return a + b + c;
}

var curry = function( func ){
  
  var args = Array.prototype.slice.call( arguments, 1 );  // <-- curry() 함수로 넘어온 인자를 args 변수에 고정
  
  return function(){
    return func.apply(null, args.concat(Array.prototype.slice.call(arguments)) );
  }
  
}

var new_func1 = curry(calculate, 10); 
console.log(new_func1(2,3)); // 10 + 2 + 3 = 15출력


위 예제로 만들어진 curry() 함수의 역할은

curry() 함수로 넘어온 인자를 args에 담아놓고, 새로운 함수 호출로 넘어온 인자와 합쳐서 함수를 적용한다.





15] 메모이제이션(Memoization)

- 메모이제이션은 계산 결과를 함수의 프로퍼티 값으로 담아놓고 나중에 사용할 수 있다.


- 함수의 연산된 값을 저장해두므로 중복 연산을 피할 수 있어 불필요한 작업을 줄일 수 있다.


재귀함수때 잠깐 봤던 피보나치 수열로 다시 예를 들자면



//메모이제이션 미 사용
var count = 0;

var fibonacci_1 = function( n ){
  
  count ++;
  
  if( n === 0 || n === 1 ){
    return 1;
  }else {
    return fibonacci_1(n-1) + fibonacci_1(n-2);
  }
  
}

for (var i = 0; i < 10; i++){
  
  console.log( fibonacci_1(i) );
  
}

console.log('count : ' + count); // count : 276 출력

위 코드는 문제가 없으나, 수열의 10번째 칸 까지의 계산을 할때 fibonacci_1() 함수가 276번이나 호출된다.

이 코드에 메모이제이션 패턴을 사용해서 보면

//메모이제이션 사용
var count = 0;

var fibonacci2 = function(){
  
  var memo = [1, 1];  // <-- 결과값을 저장해두는 배열
  
  var fib = function(n) {
    
    count ++;
    var result = memo[n];  // <-- 클로저를 통해 memo 배열에 접근
    
    if (typeof result !== 'number') {  // <-- 결과값이 없는 경우에만 수행
      result = fib(n-1) + fib(n-2);
      memo[n] = result;    // <-- 결과값 대입
    }
    
    return result;
  };
  
  return fib;
  
}();

for (var i = 0; i < 10; i += 1) {
  console.log( fibonacci2(i) );
}

console.log("count : " + count);  // count : 29출력

fibonacci_2() 함수가 호출되면 제일 먼저 결과가 저장되어 있는지를 확인 한 후 저장된 값이 있으면 연산을 수행하지 않고 바로 결과를 반환한다.

이 함수는 fibonacci_1() 함수와 결과는 같지만, 함수 호출은 29번만 된다.


'Web > Javascript' 카테고리의 다른 글

배열  (0) 2018.02.28
상속  (0) 2018.02.27
함수 - (스코프, 클로저)  (0) 2018.02.26
함수  (0) 2018.02.26
객체  (0) 2018.02.26

댓글