본문 바로가기

Web Development/Front-end

[Zerocho-10] 반응속도 테스트 게임 ( 호출스택, new Date() )

중급 강좌 부터는 따로, 코드리뷰 없이 진행합니다.

 

-이번시간 주요 이론 내용

- 게임 코드

 

위와 같이 구조를 잡고 포스팅을 이어나갈 계획입니다.

 

1. classList.contains('class')

아래와 같은 HTML코드가 있다고 가정합시다.

//HTML
<h1 id='screen' class='wating'> 웨이팅 클래스 </h1>

아래 JS코드에서 classList.contains를 이용해보겠습니다.

let screen = document.querySelector('#screen');

if(screen.classList.contains('waiting')){
	console.log(`클래스가 waiting입니다.`);
} else {
	console.log(`클래스가 waiting이 아닙니다.`);
}

이렇게하면, 위에서 선언한 HTML 코드를 screen변수에 할당해주고,

위 HTML 태그에 class가 'waiting' 인지 아닌지 확인해서 True or False로 반환합니다.

tag.classList.add('className') // -> 태그에 ClassName을 추가(생성)합니다.
tag.classList.remove('className') // -> 태그에 ClassName을 삭제합니다.
tag.classList.contains('className') // -> 태그에 ClassName의 유무를 확인합니다.

 

 

2. new Date();

new Date함수는 코드 그대로 새로운 시간을 생성(현재시간기준) 해줍니다.

let a = new Date();
let b = new Date();

console.log(a); // Thu Oct 22 2020 23:07:44 GMT+0900 (대한민국 표준시) {}
console.log(b - a); // 마지막 시간 - 현재시간 의 값이 출력됩니다.

new Date는 현재시간을 생성해주는 코드이며, 두 값을 빼서 시간차를 구할 수도 있습니다. 이 new Date()만으로도 충분하지만, 혹시라도 정밀한 0.000000001초 의 간격을 재야한다고 한다면, performance.now()를 통해 new Date()와 똑같이 이용하면서 좀 더 정밀한 시간차를 구할 수도 있습니다.

 

3. setTimeout()  & setInterval() & clearTimeout();

//setTimeout() -> 설정시간 이후 1회 실행함.

setTimeout(()=>{
	실행내용
}, 시간);

//setInterval() -> 설정시간 이후 실행 반복함.

setInterval(()=>{
	실행내용
}, 시간);


//clearTimeout() -> setTimeout이나, setInterval을 제거해서 멈추게함.

clearTimeout(멈출 setinterval or setTimeout);

 

 

4. 호출스택

호출스택이란, 호출하면, 스택이라는 바구니가 생기는데 그 바구니에 넣어지고, 또 후입선출식으로 빠져나온다는 개념이에요.

그 바구니에는 크기의 한계가 있고, 스택의 범위를 넘어가면, 오류가 터져나옵니다.

이 개념을 이해해 봅시다.

예를들어 다음과 같은 코드가 있습니다.

//함수선언
function a(){
	console.log('a');
}
function b(){
	console.log('b');
}
function c(){
	console.log('c');
}
function d(){
	console.log('d');
}


//함수호출
a();
b();
c();
d();

함수를 선언하고 호출했습니다.

그럼, 스택이라는 또 다른 저장공간이 생기고 그게 콘솔에 입력되면서 날라가 버리는 건데요. 동영상으로 봅시다.

좌측 스택  && 우측 콘솔

위에 함수를 선언한 것은 스택에 아무런 영향이 없구요.

아래에서 a()함수를 먼저 실행했으니, Function a가 스택에 담깁니다. 그리고 console.log() << 얘도 함수거든요. 얘도 그 다음에 담겨요.

그리고나서 컴퓨터는 먼저 넣은 것을 나중에 실행시키는데요. (후입선출방법)

그래서 콘솔에 a가 찍히고, console.log('a')가 실행됐으니, 스택에서 사라지고, 그리고 이제 function a도 더이상 할일이 없으니 사라집니다.

이와 같은 루프를 a, b, c, d 모든 함수가 거치게되죠. 이런 것을 호출 스택이라고 합니다.

 

 

이제 호출스택을 이용해, 다음 문제를 풀어보겠습니다.

 

1. 아래 코드를 보고, 콘솔에 어떻게 찍힐지 순서대로 나열해보시오.

function d(){
    console.log('d');
}
function e(){
    console.log('e');
}
function a(){
    function b(){
        function c(){
            console.log('c');
        }
        c();
        console.log('b');
    }
    b();
    console.log('a');
}

d();
e();
a();

어떻게 찍힐까요?

1. 우선, d()함수를 호출했으니, d가 찍힐 것 입니다.

2. 그리고 e()함수를 호출했으니, e가 찍히고,

3. 여기가 하이라이트인데, a()함수를 실행합니다. 그랫더니, b()함수가 선언되고, b()함수를 실행시킵니다.

4. b함수에 c함수를 선언했어요. 그리고 c(); 함수를 실행시키래요. 그래서, c함수를 실행시켰더니, console.log('c')가 출력됩니다.

5. 그리고, c함수를 실행시킨뒤에 console.log('b'); 를 실행시키래요. 그래서 'b'가 출력됩니다.

6. 그리고 b();함수는 다 실행시켰죠? 그래서 console.log('a')가 출력됩니다. 그래서 'a'가 출력되요.

 

그럼, 실행은 d -> e -> c -> b -> a 이렇게 실행되겠죠?

 

 

연습문제 2

function d(){
    console.log('d');
}
function e(){
    console.log('e');
}
function a(){
    function b(){
        function c(){
            console.log('c');
        }
        console.log('b');
        c();
    }
    b();
    console.log('a');
}

d();
e();
a();

 

 

연습문제 3

function d(){
    console.log('d');
}
function e(){
    console.log('e');
}
function a(){
    function b(){
        function c(){
            console.log('c');
        }
        console.log('b');
        c();
    }
    console.log('a');
    b();
}

d();
e();
a();

 

실행시키기전에 미리 한번 머릿속으로 생각해보고, 어떻게 출력될지 나열한 후에, 실행시켜보세요.

 

 

5. 반응속도 게임 영상

반응속도게임영상

 

6. 반응속도게임 코드

response.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>반응속도게임</title>
    <style>
        #screen {
            font-weight: bolder;
            font-size: xx-large;
            width: 500px;
            height: 500px;
            text-align: center;
            user-select: none;
        }
        #screen.waiting{
            background-color: aqua;
        }
        #screen.ready{
            background-color: red;
            color: white;
        }
        #screen.now{
            background-color: green;
            color: white;
        }
        #result{
            font-weight: bolder;
            font-size: xx-large;
            color: blueviolet;
        }
    </style>
</head>
<body>
    <div id='screen' class='waiting'>클릭해서 게임을 시작하세요 !</div>
    <div id='result'></div>
    <script src='response.js'></script>
</body>
</html>

HTML과 CSS를 통해 만들어줬습니다.

 

response.js

let screen = document.querySelector('#screen');
let result = document.querySelector('#result');
let start_time; //스코프 해결
let end_time; //스코프 해결
let time_out;


screen.addEventListener('click', () => {
    //게임시작 = 빨간화면
    if(screen.classList.contains('waiting')){
        screen.classList.remove('waiting');
        screen.classList.add('ready');
        screen.textContent = '초록색이 되면 클릭해주세요 !!';
        //초록색화면으로 갑자기 넘어가게 하는 부분 !
        time_out = setTimeout(()=> {
            start_time = new Date();
            screen.click();
        }, Math.floor(Math.random() * 1000)+ 2000);

    //초록화면 !! 클릭해야함 !!
    } else if (screen.classList.contains('ready')){
        //빨간색일 때 클릭하면?
        if(!start_time){
            clearTimeout(time_out);
            screen.classList.remove('ready');
            screen.classList.add('waiting');
            screen.textContent = '초록색으로 화면이 변하면 눌러주세요 ! 다시 클릭해서 게임을 시작하세요 !';
        } else {
            screen.classList.remove('ready');
            screen.classList.add('now');
            screen.textContent = '나를 클릭해라 !';
        }

    //대기화면 !
    } else if (screen.classList.contains('now')){
        end_time = new Date();
        let result_time = end_time - start_time; //화면이 변한 시각과 사용자가 클릭한 시간의 시간차. 즉, 반응속도 시간측정.
        result.textContent = `당신의 반응속도는 ${result_time} 입니다. (단위 ms, 낮을수록 빠른 것.)` //결과창
        start_time = null; //시간 초기화
        end_time = null; //시간 초기화
        screen.classList.remove('now');
        screen.classList.add('waiting');
        screen.textContent = '클릭해서 게임을 시작하세요 !';
    }
})