자바스크립트/인프런강의-렛츠기릿 자바스크립트

6강 로또 추첨기 - sort, setTimeout, 블록,함수 스코프,클로저

샐님 2023. 7. 5. 12:01
728x90
반응형

1. 비동기 - 코드 순서대로 실행되지 않고 특정한 동작을 했을 때 실행되는 행위. 동기의 반대

 

2. sort 

  - 정렬하는 함수, 숫자 나 문자도 정렬됨.

 
   const array = [1, 4, 3, 8, 5, 9, 7];
 
 // 오름차순으로 정렬되지만 원본이 훼손됨.
 array.sort((a, b) => {
                return a - b
            })
 
// 내림차순으로 정렬
 array.sort((a, b) => {
                return b - a
            })
 
// slice()를 사용해서 복사한다. 원본을 훼손하지 않는다. 
 
        array.slice().sort((a, b) => {
            return a - b
        });
 
 //문자열 첫번째글자의 코드넘버를 비교해서 정렬한다.
 const fruitsarray = ['apple', 'banana', 'kiwi', 'orange', 'grape'];
        fruitsarray.slice().sort((a, b) => a[0].charCodeAt() - b[0].charCodeAt())
// ['apple', 'banana', 'grape', 'kiwi', 'orange']
 //문자열정
       fruitsarray.slice().sort((a, b) => a.localeCompare(b))
 

 

3. setTimeout()

    - 자바스크립트의 타이머의 시간은 정확하지 않다. 기본적으로 자바스크립트는 한 번에 한가지 일만 할수 있다. 이미 많은 일을 하고 있다면 설정한 시간이 되어도 setTimeout에 지정된 작업이 수행되지않는다. 기존에 하고 있던 일이 끝나야 setTimeout에 지정한 작업이 실행된다.


        setTimeout(() => {

            //특정시간후에 실행될 함수
        }, 밀리초) // 밀리초 : 천분의일
 
 setTimeout(() => {
         func()
        }, 8000)
 
setTimeout(func,8000)
 
 

 

4. var 와 let 의 차이

 var - 함수 스코프(함수만 신경쓴다.)

let -블록 스코프 (if,switch,for 등)

 


        if (true) {
            var a = 1;
        }
        console.log(a);
       //1
    
        if (true) {
            let b = 1;
        }
        console.log(b);
      // 블록 스코프라서 if문밖에서 접근안됨
      Uncaught ReferenceError ReferenceError: b is not defined
 

 

 

  - var는 블록과 관계없이 돌아간다. for문이 끝났을 때 i 가 5가 되어있다.

       for (var i = 0; i < 5; i++) {}
        console.log(i);
     //5
 
 
 for (let j = 0; j < 5; j++) {}
        console.log(j);
 
Uncaught ReferenceError ReferenceError: j is not defined
 

 

 

 - 비동기와  var(함수 스코프)가 만나면 클로저 문제가 발생

 

 

for (var i = 0; i < 6; i++{

            let time = (i + 1* 1000;

            setTimeout( () => {                            

                showball(i, 'result');

            }, time)

        }

-형광색친 부분(콜백함수) 안에 든 i와 바깥의 time 은 다른 시점에서 실행됨.
Time은 반복문을 돌 때 실행되고 setTimeout 의 콜백함수는 지정한 시간 뒤에 호출함. 그런데 반복문은 빠른 속도로 돌기때문에 콜백 함수가 실행 될때는 이미 i6이 되어있다.
        }
 
 클로저를 사용해서 문제해결함.

   for (var i = 0; i < 6; i++) {

            let time = (i + 1) * 1000;

            (function(j) {

                setTimeout(() => {

                    showball(i, 'result');

                }, time);

            })(i);


       
}

 

 

 이러한 문제 떄문에 let 을 사용함

 

 

5. 로또추점기 전체 코드

 

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <title>로또추첨기</title>
    <style>
        .ball {
            display: inline-block;
            border: 1px solid black;
            border-radius: 20px;
            width: 40px;
            height: 40px;
            line-height: 40px;
            font-size: 20px;
            text-align: center;
            margin-right: 20px;
        }
    </style>
</head>

<body>
    <div id="result">추첨 결과는? </div>
    <div id="bonus">보너스: </div>
    <script>
        const candidate = Array(45).fill(0).map((el, index) => {
            return index + 1;
        }); // 45개

        // 램덤으로 candidat배열을 섞고 난 후에 앞에서 7개만가져온다.
        // 피셔-예이츠 셔플 알고리즘 이용
        const shuffle = [];
        while (candidate.length > 0) {
            const random = Math.floor(Math.random() * candidate.length);
            const spliceArray = candidate.splice(random, 1);
            const value = spliceArray[0];
            shuffle.push(value);

        }

        const winBalls = shuffle.slice(0, 6).sort((a, b) => a - b);
        const bonus = shuffle[6];

        const $result = document.querySelector("#result");
        const $bonus = document.querySelector("#bonus");
        const showball = (number, $target) => {
            const $ball = document.createElement('div');
            $ball.className = 'ball';
            $ball.textContent = winBalls[number];
            console.log($target)
            if ($target == 'result') {
                $result.appendChild($ball);
            }
        }
        for (let i = 0; i < 6; i++) {
            let time = (i + 1) * 1000;
            setTimeout(() => {
                showball(i, 'result');
            }, time)
        }

        for (let i = 0; i < 6; i++) {
            let time = (i + 1) * 1000;
            setTimeout(() => {
                showball(i, 'result');
            }, time)
        }

        setTimeout(() => {
            const $ball = document.createElement('div');
            $ball.className = 'ball';
            $ball.textContent = bonus;
            $bonus.appendChild($ball);
        }, 8000)
    </script>
</body>
728x90
반응형