클래스(Class) + 콜백(Call back)

seul_velog·2021년 12월 27일
0

JS note

목록 보기
3/9
post-thumbnail
post-custom-banner

✍️ 클래스와 콜백 알아보기

  • 다양한 오브젝트를 만들기 위한 청사진 '클래스'에 대해 예제를 통해 정리해 보자.


1. 숫자가 0부터 1씩 증가하다가, 5배수가 될 때마다 알려주는 카운터 클래스 만들기

class Counter {
    constructor(){
        this.counter = 0; // 필드
    }

    increase() {  // 증가되는 increase 함수
        this.counter++;
        console.log(this.counter);
        if(this.counter % 5 ===0 ){  // 5배수일 때마다 알리기
            console.log('check!')
        }
    }
}

const coolCounter = new Counter();
coolCounter.increase();  // 1
coolCounter.increase();  // 2
coolCounter.increase();  // 3
coolCounter.increase();  // 4
coolCounter.increase();  // 5  // check!
coolCounter.increase();  // 6

✍️ MEMO

  • Counter라는 클래스에는 자체적으로 counter 라는 변수가 있다.
  • Counter는 클래스를 이용해서 object 를 만드는 순간 '0'으로 초기화가 된다.
  • 클래스 안에서 함수를 선언할 때는 function 이라고 따로 작성하지 않아도 된다.
  • increase() 함수를 호출할 때마다 카운터의 숫자를 하나씩 증가 시킨다.
  • coolCounter 라는 변수에 클래스를 이용해서(new연산자 이용) 오브젝트를 만든다.
  • new 연산자를 이용해서 클래스를 만들게 되면, constructor 가 실행되고 this.counter 를 '0'으로 초기화 한다.

→ Counter라는 클래스 안에는 counter 변수, increase 함수가 있다.

coolCounter 변수는, 만들어진 오브젝트를 가르키고 있고, 그 오브젝트에 increase() 함수를 호출할 때마다 클래스 안에 있는 카운터라는 데이터가 하나씩 증가한다.


❓ 문제점

  • 카운터 클래스 자체에서 사용되므로, coolCounter 를 쓰는 사람이 원하는대로 세밀하게 조절하기 힘들다.
  • 즉, 'check!' 말고 다른 걸 출력하고 싶거나, 콘솔출력이 아니라 alert을 하는 등 다양한 변화를 주고싶을 때 원하는대로 컨트롤 하기 힘들다.


2. 콜백함수를 통해서, 사용자 필요에 따라 출력을 컨트롤 할 수 있도록 만들기

class Counter {
    constructor(){
        this.counter = 0; // 필드
    }

    increase(runIf5Times) {  // 증가되는 increase 콜백함수
        this.counter++;
        console.log(this.counter);

        if(this.counter % 5 ===0 ){  // 5배수일 때마다 알림
            runIf5Times(this.counter);  // 숫자를 정확히 알기 위해서 this.counter
        }
    }
}

const coolCounter = new Counter();

function printSomething(num) {  // 콘솔출력 함수
    console.log(`${num} : hello !`);
}
function alertSomething(num){  // 팝업알림 함수
    alert(`${num} : Hi~`);
}

coolCounter.increase(printSomething);  // 1
coolCounter.increase(printSomething);  // 2
coolCounter.increase(printSomething);  // 3
coolCounter.increase(printSomething);  // 4
coolCounter.increase(printSomething);  // 5  // 5 : hello !

coolCounter.increase(alertSomething);  // 6
coolCounter.increase(alertSomething);  // 7
coolCounter.increase(alertSomething);  // 8
coolCounter.increase(alertSomething);  // 9
coolCounter.increase(alertSomething);  // 10  // 10 : Hi~ 팝업창이 뜸

✍️ MEMO

  • increase 에 콜백함수 runIf5Times 를 받고 if 문을 통해 원할 때 출력 받을 수 있도록 작성한다.
  • 컨트롤하고 싶은 함수를 각각 정의해서 호출한다.
  • 숫자를 정확히 알고 싶다면 runIf5Times(this.counter) 를 통해서 인자를 전달하고, 각각의 함수에서 그 인자를 전달 받아서 출력한다.

❓ 장점

  • 프린트를 check! -> hello ! 로 자유롭게 변경가능, printSomething 대신 alertSomething 함수를 새로 정의함으로써, 팝업알림도 받을 수 있게 되었다.

→ 콜백함수를 전달함으로써 원하는 기능을 수행할 수 있게 되었다.

class Counter 라는 것은 숫자가 5배가 될 때마다 어떤 동작을 하는지는 자체적으로 결정되어있지 않다. 그래서 사용자가 원할 때 원하는 함수를 전달하게 되면 그것에 맞춰서 수행되어진다.


❓ 문제점

  • increase 라는 함수를 호출할 때마다 인수를 전달하는 과정이 번거롭고 중복적이다.


3. 클래스에 원하는 콜백함수를 전달하도록 만들기

class Counter {
    constructor(runEveryFiveTimes){ // 콜백함수를 받도록 수정
        this.counter = 0;
        this.callback = runEveryFiveTimes; // callback 변수에 할당
    }

    increase() {  
        this.counter++;
        console.log(this.counter);

        if(this.counter % 5 ===0 ){  
            this.callback(this.counter);  
        }
    }
}
function printSomething(num) {  // 콘솔출력 콜백함수
    console.log(`${num} : hello !`);
}
function alertSomething(num){  // 팝업알림 콜백함수
    alert(`${num} : Hi~`);
}

const coolCounter = new Counter(printSomething); // 콜백함수 전달
// const coolCounter = new Counter(alertSomething);



coolCounter.increase();  // 1
coolCounter.increase();  // 2
coolCounter.increase();  // 3
coolCounter.increase();  // 4
coolCounter.increase();  // 5  // 5 : hello !

coolCounter.increase();  // 6
coolCounter.increase();  // 7
coolCounter.increase();  // 8
coolCounter.increase();  // 9
coolCounter.increase();  // 10  // 10 : hello !

✍️ MEMO

  • constructor 에서 콜백 함수를 받을 수 있도록 작성한다.
  • constructor 함수 이므로 인자를 받아와서 함수내에서 작동(기억)되도록 callback 이라는 변수에 runEveryFiveTimes 를 할당한다.
  • 이제 카운터 내부의 increase 함수의 if 문에서 callback 변수를 통해 콜백을 받아올 수 있으며, increase 함수를 호출할때 인자를 적지 않아도 된다.
  • new Counter 생성자에 원하는 콜백함수를 전달한다.
  • increase 가 호출 될 때마다 if 문의 조건이 만족되면 this.callback 함수를 호출한다. 호출할 때 카운터 안에있는 (this.counter) 데이터를 전달한다.
  • this.callbackprintSomething 을 가리키고 있기 때문에 이 함수가 수행된다.

→ Counter 안에는 두가지의 데이터 타입이 들어가게 되었다. (1) counter 를 0으로 초기해주는 변수 (2)callback 변수

coolCounter 라는 오브젝트로 Counter라는 클래스의 청사진을 이용해서 오브젝트를 만들었는데, (1)counter 는 그대로 0을 가르키고, (2)callbackprintSomething 을 가리킨다.


❓ 문제점
만약 const coolCounter = new Counter(printSomething); 에서 printSomething 이라는 콜백함수를 전달하지 않는다면 에러가 발생한다.

  • Counter라는 클래스는, 클래스를 만들때 콜백함수를 하나 전달 받는다. 그래서 new Counter() 를 통해서 카운터를 만들때, 어떤 콜백을 전달할지 지정하지 않으면, counstructor 의 인자는 undefined 가 된다. 결국 클래스 내부의 this.callbackundefined 가 된다.

  • 실행시키면 TypeError 가 뜬다. this.callbackundefined 이고, 이것은 function 이 아니기 때문이다.

  • 그래서 this.callbackundefined or true 확인 후, 콜백을 부르도록 만들어야한다.



4. 클래스를 만들 때, 사용자가 콜백함수를 등록하면 호출되고, 등록된 콜백함수가 없다면 호출해서는 안되도록 만들기

increase() {  
        this.counter++;
         console.log(this.counter);
  
	// this.callback && this.callback(this.counter); 간단하게 작성할 경우
        if(this.counter % 5 ===0 ){ 
            if(this.callback){
                this.callback(this.counter);
            }
        }
    }
}

✍️ MEMO

  • 타입스크립트는 인자가 정말 필요한지 옵션인지에 대해 타입에서 명시할 수 있다. ex.) runEveryFiveTimes : function?
  • JavaScript는 타입을 명시하지 않기 때문에 위와 같이 작성 해준다.

AND 연산자 &&

  • AND 연산자 &&if 문을 ‘짧게’ 줄이는 용도로 사용할 수 있는데, &&의 오른쪽 피연산자는 평가가 && 우측까지 진행되어야 실행된다.

  • 즉, 여기서는 좌측이 true 인 경우에만 this.callback(this.counter) 문이 실행된다.

  • && 를 사용한 코드가 더 짧지만, if 문을 사용한 예시가 코드에서 무엇을 구현하고자 하는지 더 명백히 드러내고, 가독성도 좋다고 한다. 그러므로 때에 따라서 if 조건문이 필요하면 if 를 사용하고, AND 연산자는 연산자 목적에 맞게 사용하는 것이 좋다고 한다. 🤔



✍️ MEMO

  • 클래스에 원하는 기능을 다 정의하게 되면, 사용자가 세밀하게 컨트롤하거나 재사용성이 떨어진다.
  • 콜백함수를 이용해서 클래스를 정의하게 되면, 사용자가 원하는대로 호출할 수 있다.
  • 하나의 클래스로 다양한 오브젝트를 만들어서 서로 다른 기능을 수행할 수 있도록 작성한다면, 재사용성이 높아진다.
  • 클래스를 모든 기능을 수행하는 완전체로 만들기 보다는 원하는 기능을 끼워 맞춰서 재조립이 가능하도록 만드는 것이 포인트이다. 😀
profile
기억보단 기록을 ✨
post-custom-banner

0개의 댓글