초기화버튼, Number와 String의 사칙연산

ES2020 초급 웹게임 강좌 : 계산기


1. 값을 초기화를 하려면 보통 null이나 undefined 사용.

초보자는 null추천

1
2
3
4
5
6
clearbtn.addEventListener('click', ()=>{ //clearbtn클릭시 초기화
numberInput.value = null;
temp = null ;
operator = null;
resultInput.value = null;
})

2. Number 와 String의 사칙연산

숫자와 문자열을 더하면(+) 숫자가 문자열로 바뀌어서 계산됨
ex) 10 + ‘5’ = ‘105’ (결과값이 문자열)

숫자와 문자열을 곱하기,빼기,나누기는 문자열이 숫자로 바뀌어서 계산됨
ex) 10 / ‘5’ = 2 , ‘10’ * 5 = 50 , ‘10’ - ‘5’ = 5 (결과값이 숫자)

3. Falsy 값을 가지는 6가지 (암기필수)

There are only six falsey values in JavaScript:
undefined , null , NaN , 0 , “” (empty string), and false.

웹 게임을 만들며 배우는 JS 완강 후기

웹 게임을 만들며 배우는 JS 완강 후기

웹 게임을 만들며 배우는 JS 완강 후기

온라인 인강을 혼자 수강한 경험이 있는 사람들은 많이 공감할 것이다.
강의를 100% 수강하기가 굉장히 어렵다는 사실을.
그 어려운 걸, 제가 해냅니다!!!
이 강의는 코드스테이츠 pre 코스를 수강하면서 부족한 나의 JS 실력을 쌓고자 들었던 무료강의이다.

Read More

isNaN(), parseInt(), 연속된 숫자생성3종세트Array().fill().map(), 뽑은 숫자들을 랜덤도splice(Math.floor(Math.random()*arr.length, n)

웹 게임을 만들며 배우는 JS : 지뢰찾기

isNaN(), parseInt(), 연속된 숫자생성3종세트Array().fill().map(), 뽑은 숫자들을 랜덤도splice(Math.floor(Math.random()*arr.length, n)

1.isNaN()

isNaN()는 value가 Not-A-Number인 경우 true를 return한다. return type은 boolean이다.

즉 숫자가 아닌 것을 찾는 함수다.

1
2
3
4
5
6
7
8
console.log(isNaN(2));
// expected output: false 숫자아님? 놉! 숫자임

console.log(isNaN('me'));
// expected output: true 숫자아님? 얍! 숫자아님

console.log(isNaN('2'));
// expected output: false 숫자아님? 놉! 숫자임

참고로
Number.isNaN(https://www.w3schools.com/jsref/jsref_isnan_number.asp) 와

isNaN()(https://www.w3schools.com/jsref/jsref_isnan.asp)은 완전히 다르다.

2. parseInt()

parseInt()는 문자열을 구분하고 정수로 변환한다.

1
2
3
4
5
6
7
8
9
10
11
function roughScale(x, base) {
var parsed = parseInt(x, base);
if (isNaN(parsed)) { return 0 }
return parsed * 100;
}

console.log(roughScale(' 0xF', 16));
// expected output: 1500

console.log(roughScale('321', 2));
// expected output: 0

코딩공부하면서 수학공부를 다시 하게 된다ㅋㅋㅋㅋㅋ하… 대환장파티

정수가 뭐였더라?

number type

3. 연속된 숫자생성 3종세트

지뢰 위치를 뽑기 위해 0부터 99까지의 숫자를 생성해야한다.

이때 암기해두면 좋은 함수 3가지가 있다.

Array().fill().map()꼭 암기할것

연속된 숫자생성에 필요한 3종세트라고 생각하면된다

Array(n)로 => n개의 빈 배열을 만들고

fill()로 => 빈 배열을 undefined로 채워고

map()으로 => n개의 빈 배열과 n개의 undefined를 1대1매칭 시켜준다

예를들어 for문 안쓰고 3~50까지 숫자만들고 싶을때 유용하다.

1
2
3
4
5
//step3. 지뢰 위치 뽑기
var 후보군 = Array(hor*ver).fill().map(function(요소, 인덱스){
return 인덱스 //0부터 99까지 인덱스를 리턴. 1~100까지하고싶으면 인덱스+1 하면 됨
});
// 100개의 숫자를 만들고 칸에 fill채워주고 map으로 숫자와 칸을 1대1매칭시켜준다

4. 뽑은 숫자들을 랜덤하게 나타내기

후보군으로 뽑은 숫자들을 랜덤하게 나타나게 하고 싶을 때 아래와 같이 코딩한다

1
2
3
4
5
var 셔플 = [];
while (후보군.length > 80){ //지뢰는 20개만 필요하므로 100개중애 80개는 안쓴다
var 이동값 = 후보군.splice(Math.floor(Math.random()*후보군.length), 1)[0];
셔플.push(이동값); //랜덤하게 순서를 섞어서 셔플배열에 넣어준다
}

Math.random(), Math.floor/ceil/round, forEach와map, for반복문과while반복문사용차이, .sort(오름차순정렬) setTimeout(function (){} , 밀리초)

웹 게임을 만들며 배우는 JS : 로또추첨기

Math.random(), Math.floor/ceil/round, forEach와map, for반복문과while반복문사용차이, .sort(오름차순정렬) setTimeout(function (){} , 밀리초)

1. Math.random()

랜덤한 수를 뽑는 매서드이다.

1
2
3
4
5
6
Math.random() 에서 * n을 하면, n전까지의 숫자가 random으로 나온다.
보기쉽게 소수점첫째자리 버림 하는 함수인 Math.floor()와 함께 주로 사용한다.
예를들어

Math.floor(Math.random()*5)
//=> 0,1,2,3,4 숫자들이 랜덤으로 출력됨.

2. Math.floor()와 Math.ceil()와 Math.round()

세가지의 차이점은

1
2
3
Math.floor() : 소수점 버림. 정수로 반환. 
Math.ceil() : 소수점 올림. 정수로 반환.
Math.round() : 소수점 반올림. 정수로 반환.

3. .forEach(function(){})와 .map(function(){})

STEP1. 로또 숫자 만들기(1~45까지)

1
2
3
4
5
6
7
8
9
10
11
12
var 후보군 = Array(45); 
//empty가 45개 생기고 empty의 특징은 foreach반복문 적용 불가.
var 필 = 후보군.fill();
//필을 해줘야 45개의 emtpy에서 undefined가 된다.empty가 아니기에 forEach반복문 실행가능해짐.

//forEach를 사용해서 억지로 숫자를 넣을 수 있다.
필.forEach(function(요소,인덱스) {
필[인덱스] = 인덱스 + 1;
});

console.log(필);
//=> (45) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]

더 좋은 방법이 있다. 바로 maping이다.
.map(function(){})은 array 요소와 1대1로 mapping이 된다.

1
2
3
4
5
6
7
8
var 후보군 = Array(45); 
var 필 = 후보군.fill();
var 맵 = 필.map(function(요소, 인덱스){
return 인덱스 + 1
});

console.log(맵);
//=> (45) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]

굳이 변수를 3개씩 많이 지정할 필요가 없다. 위의 전체를 변수 1개로 그리고 단 세 줄로 나타낼 수 있다.

1
2
3
4
5
var 후보군 = Array(45).fill().map(function(요소, 인덱스){
return 인덱스 + 1
});
console.log(후보군);
//=> (45) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]

세상 깔~끔!

4. for반복문과 while반복문 사용차이

STEP2. 숫자를 랜덤하게 섞고 총7개 숫자를 뽑기

숫자를 랜덤하게 섞은 뒤 7가지의 숫자를 뽑고자 한다면 흔히 for문을 먼저 생각할 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var 셔플 = [];
for (var i=0; i<후보군.length; i+=1){
var 이동값 = 후보군.splice(Math.floor(Math.random()*후보군.length), 1)[0];
셔플.push(이동값);
}
console.log('---')
console.log('후보군길이: '+후보군.length); //=>22개
console.log('셔플길이: '+셔플.length); //=>23개

// 후보군길이 + 셔플길이 = 45 개 된다.
// 즉, 기존 후보군길이 45개에서 셔플로 23개 빠지고 나머지 22개만 남게된다.

console.log('후보군: '+후보군.sort(function(p, c){ return p-c;}));
console.log('셔플숫자: '+셔플.sort(function(p, c){ return p-c;}));

하지만 for반복문을 못 쓰지 못한다.

후보군길이 + 셔플길이 = 45 개 된다. 즉, 기존 후보군길이 45개에서 셔플로 23개 빠지고 나머지 22개만 남게된다.

후보군.length가 45개에서 22개로 줄어들면 우리가 원하는데로 45개에서 랜덤숫자 7개를 뽑을 수 없다.

지금 23개에서 랜덤숫자 7개 뽑는 꼴이 되버림. 따라서 이럴 때는 while을 쓴다.

1
2
3
4
5
6
7
8
9
10
11
12
13
while (후보군.length>0){
var 이동값 = 후보군.splice(Math.floor(Math.random()*후보군.length), 1)[0];
셔플.push(이동값);
}
console.log('---')
console.log('후보군길이: '+후보군.length); //=> 0개
console.log('셔플길이: '+셔플.length); //=> 45개

// 후보군길이 + 셔플길이 = 45 개 된다.
// 즉, 기존 후보군길이 45개에서 셔플로 45개 빠지고 나머지 0개만 남게된다.

console.log('후보군: '+후보군.sort(function(p, c){ return p-c;}));
console.log('셔플숫자: '+셔플.sort(function(p, c){ return p-c;}));

for반복문은 내가 몇번 반복해야할 지 정확히 알 때 사용하면 좋고,

while반복문은 내가 몇번 반복해야할 지 모를 때, 그리고 기준값이 계속 변경될때 사용하면 좋다.

여기서 기준값은 후보군.length다.

이렇게 뽑은 랜덤한 7개의 숫자는 아직 console.log를 통해 볼 수 밖에 없다.

따라서 화면에 구현하는 방법은 html로 결과창태그를 만든 뒤

js상으로 결과창태그를 불러와서 뽑은 랜덤당첨숫자들이 결과창태그의 자식태그로 들어가면 된다.

1
2
3
<div id='결과창'>
<div>여기에 각 당첨숫자태크가 갯수만큼 자동으로 생겨야함<div> //그렇다면 for문이겠지?
</div>
1
2
3
4
5
6
7
8
9
//1.html상의 결과창태그를 js로 가져오는 방법은 두가지이며 아래 5번에서 자세히 설명함!
var 결과창 = document.getElementById('결과창');

//2.뽑힌 숫자들을 결과창태그의 자식태그로 넣기
for(let i=0; i<당첨숫자들.length; i+=1){
var 공 = document.createElement('div'); //i번만큼의 div태크 만들고
공.textContent = 당첨숫자들[i]; //div태크안에는 뽑힌 당첨숫자들을 하나씩 넣고
결과창.appendChild(공); //결과창태크의 자식태그로 넣는다
}

5. JS에서 html태그를 불러오는 2가지 방법

첫번째, getElementById 와 getElementsByClassName 를 이용하기

두번째, querySelector 와 querySelectorAll를 이용하기(권장)

1
2
3
4
5
6
7
<body>
<div>당첨 숫자는? ㄷㄱㄷㄱㄷㄱ</div>
<div id='결과창'></div>
<div>보너스숫자</div>
<div class='보너스'></div>
<script src = "로또추첨기.js"></script>
</body>

이 태그들 중 결과창과 보너스를 js로 가져오는 방법은

1
2
3
4
5
6
7
//첫번째 방법사용
var 결과창 = document.getElementById('결과창');
var 칸 = document.getElementsByClassName('보너스')[0]; //class의 경우 여러개 사용이 가능해서 꼭 뒤에 [n] 몇번째 클래스인지 적어줘야함

//두번째 방법사용
var 결과창 = document.querySelector('#결과창'); //id일 경우 #
var 칸 = document.querySelector('.보너스'); //class일 경우 .

끝!
이렇게 가지고 와서 원하는 방향으로 사용하면 된다!

6. .sort와 .sort(function(p, c){ return p-c;})

1
2
3
.sort() : 숫자 정렬
예를들어 [2,15,4,7,27].sort();
//=> [15,2,27,4,7] .

뭔가 이상한데?

첫째자리 수를 기준으로 숫자 오름차순이라서 그렇다.

15에 1이 먼저 있기때문에 15가 제일 첫번째로 정렬되었다.

우리가 원하는 오름차순은 아래와 같다. 내림차순은 덤으로 공부!

1
2
3
4
5
6
7
.sort(function(p, c){ return p-c;}) : 숫자오름차순 정렬
예를들어 [2,15,4,7,27].sort(function(p, c){ return p-c;})
//=> [2,4,7,15,27]

.sort(function(p, c){ return c-p;}) : 숫자내름차순 정렬
예를들어 [2,15,4,7,27].sort(function(p, c){ return c-p;})
//=> [27,15,7,4,2]

어떠한 원리로 정렬이 되는 걸까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[25,1,12].sort(function(p, c){ return p-c;})
//=> p-c가 0보다 크면 둘의 정렬순서를 바꿔주는 원리.

p - c
25 - 1 = 24 //=>이건 0보다 크므로 [1,25,12]로 정렬순서가 바뀐다.
// 그리고 바뀐 정렬순서에서 다시 실행.

p - c
25 - 12 = 13 //=>이건 0보다 크므로 [1,12,25]로 정렬순서가 바뀐다.
//그리고 처음부터 다시 실행.

p - c
1 - 12 = -11 //=>이건 0보다 작으므로 순서를 바꾸지 않는다
//그 다음 계속 실행

p - c
12 - 25 = -13 //=>이건 0보다 작으므로 순서를 바꾸지 않는다
//다 돌았으므로 정렬 끝 = [1,12,25]

숫자뿐만 아니라 문자도 비슷한 원리로 정렬이 된다고 한다.

7. setTimeout(function (){} , 밀리초)

STEP3. 화면에 로또숫자를 긴장감있게 나타내기

랜덤 숫자들이 화면에 한꺼번에 보여지는 게 아니라 시간차를 두고 나타나게 하고 싶다면 setTimeout(function (){} , 밀리초) 을 사용하면 된다.

1
2
3
4
5
setTimeout(function(){
var 공 = document.createElement('div');
공.textContent = 당첨숫자들[0]; //for문사용시 클로저문제가 발생하므로 당첨숫자들[0] ~ 당첨숫자들[5]까지 각각 적어준다.
결과창.appendChild(공);
}, 1000); //밀리초라고해서 1000 = 1초임

for문사용시 클로저문제가 발생하므로 당첨숫자들[0] ~ 당첨숫자들[5]까지 각각 적어준다.

나는 쪼랩이라 아직 클로저문제 해결법을 안 알려준다고 한다ㅋㅋㅋㅋ 나중에 중급강의에 알려준다고 하니 그때 해야지.

그럼 어떻게 하느냐? for문을 안 쓰면 된다

당첨숫자들[0] ~ 당첨숫자들[5]까지 각각 적어준다.

만약 클로저를 이용해서 푼다면 아래와 같다

1
2
3
4
5
6
7
8
for(var i=0; i<당첨숫자들.length; i+=1){
function 클로저(j){
setTimeout(function(){
공색칠하기(당첨숫자들[j], 결과창);
},(j+1) * 1000);
}
클로저(i);
}

이걸 더 짧게 줄일 수가 있는데 바로 즉시실행코드를 이용하면 된다

function을 괄호로 감싸면 즉시실행코드가 된다

1
2
3
4
5
6
7
for(var i=0; i<당첨숫자들.length; i+=1){
(function 클로저(j){
setTimeout(function(){
공색칠하기(당첨숫자들[j], 결과창);
},(j+1) * 1000);
})(i);
}
JS에서 테이블만들기, 자식태그, 2차원배열, 2차원배열클릭이벤트, forEach

동기와 비동기, split, join, indexOf, i++과 i+=1

웹 게임을 만들며 배우는 JS : 숫자야구

동기와 비동기, split, join, indexOf, i++과 i+=1

1. 동기와 비동기

동기 : 위에서 아래로 순차적으로 코드가 실행 됨.

비동기 : 순차적X, 언제 코드가 실행될 지 모름. ex) .addEventListener

2. split와 join

1
2
3
4
문자.split(구분자) -> 배열
배열.join(구분자) -> 문자

구분자 ex : ' ' 또는 ' : ' 또는 ',' 등등 다양하게 가능.

3. 배열. indexoOf

1
2
3
4
배열.indexOf(값)
값의 위치를 알 수 있다.
배열속의 0번째인지 2번째인지 등등
배열속에 없으면 -1 출력.

활용방안

1
2
3
4
5
6
7
8
9
10
11
12
let 숫자배열 = [1,3,4,5];

숫자배열.indexOf(1) //=> 0
숫자배열.indexOf(4) //=> 2
숫자배열.indexOf(8) //=> -1

어떤 배열에 내가 궁금한 숫자가 있는 지 확인하고 싶을때
for (let i =0; i<숫자배열.length; i+=1){
if (숫자배열.indexof(내가궁금한숫자) > -1){
있다 ++
}
}

4. i++ 과 i+=1

1
2
3
4
5
6
i = i + 1을 두가지 방식으로 짧게 표현할 수 있다

첫번째 : i+=1
원래 순서대로라면 i=+1이 되어야할텐데 왜 +=순서냐면, 연산자에 순서가 있는데 그중에 = 이 제일마지막에 와야하기 때문!

두번째 : i++

첫번째가 더욱 직관적이기때문에 첫번째 방식으로 공부하기를 추천함.

끝말잇기: 괄호의종류,객체벤다이어그램,배열기본,콜백함수,이벤트리스너

웹 게임을 만들며 배우는 JS : 끝말잇기

괄호의종류,객체벤다이어그램,배열기본,콜백함수,이벤트리스너


1. 대괄호 [] 중괄호 {} 소괄호 ()

2. 객체 벤다이어그램

함수는 객체지만, 객체는 함수가 아님.

배열은 객체지만, 객체는 배열이 아님.

3. 객체

= {

속성(프로퍼티) : 값(value),

속성(메서드) : 함수,

}

3-1. 객체에서 값을 가져올 때, 2가지 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

let 가랑카페 = {

커피 : '아메리카노',

가격 : 1500

}


//첫번째 방법 : 닷 노테이션

가랑카페.커피


//두번째 방법 : 브라켓 노테이션

가랑카페['커피']

방법이 두가지인 이유는? 닷노테이션은 변수를 가져오지 못한다

1
2
3
4
5
6
7

var 값 : '커피'


가랑카페.값 //=> undefined

가랑카페['값'] //=> '아메리카노'

3-2 객체에서만 쓸 수 있는 것

  • 닷 노테이션 ex) ‘안녕하세요’.length 또는 ‘*’.repeat(5)

  • 브라켓 노테이션 ex) ‘안녕하세요’[1]

여기서 잠깐!

‘안녕하세요’는 문자인데 어떻게 both 노테이션을 쓸 수 있을까? 브라우저가 자동으로 문자객체로 바꾸기 때문에 가능.

직장생활 꿀팁1. 객체 속성 값을 지우고 싶을 때는 undefined 가 아닌 null로 값을 덮어씌움으로써 내가 직접 지웠는지 아닌지 구분할 수 있다

직장생활 꿀팁2. 객체에서 값을 작성한 후 마지막 속성에도 꼭 반점(,) 을 찍어준다. 그게 실전에서 편함.

4. 배열

= [

‘사과’,

‘오렌지’,

‘포도’,

]

1
2
3
4
5

let 과일 = [ '사과', '복숭아', '배']


console.log(과일[1]) // => 복숭아

여기서 잠깐!

과일은 배열인데 어떻게 브라켓 노테이션을 쓸 수 있을까? 배열은 객체이기때문! 하지만 객체는 배열이 아님!

직장생활 꿀팁3. 그룹화하고싶지만 속성이름을 따로 주고 싶지 않을 때 배열을 사용한다.

직장생활 꿀팁4. 배열에서 값을 작성한 후 마지막 속성에도 꼭 반점(,) 을 찍어준다. 그게 실전에서 편함.

5. 무한 반복문을 끄고 싶으면 shift + esc -> 크롬관리자창에서 현재탭 종료

6. JS에서 HTML 태크 만들기

1
2
3
4
5
6
7
8
9
10
11
var 바디 = document.body;
var 단어 = document.createElement('div');
단어.textContent = '단어';
document.body.append(단어);
var 폼 = document.createElement('form');
document.body.append(폼);
var 입력창 = document.createElement('input');
폼.append(입력창);
var 등록버튼 = document.createElement('button');
등록버튼.textContent = '등록';
폼.append(등록버튼);

위와 JS와 아래의 HTML은 동일하다

1
2
3
4
5
<div>단어</div>
<form>
<input type="text" >
<button>등록</button>
</form>

7. 콜백함수

매개변수 이름은 마음대로! but 다른 사람이 봐도 알 수 있게 명확히 이름짓는 것이 포인트!

1
2
3
4
5
6
7
8
function 콜백함수 (이벤트) {}

예를 들어

function 더하기 (숫자1, 숫자2) {
console.log(숫자1 + 숫자2);
}
더하기(3, 5) //=>8

8. 이벤트리스너 = 반복문 역할 (아닐 때도 있음)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
폼.addEventListener('submit', function (이벤트) { 
//sunmit은 enter를 치면 기본적으로 새로고침이 되고 기존 기억이 리셋된다.
//그걸 방지하고 계속 진행하기 위해 아래와 같이 preventDefault를 넣어줌
이벤트.preventDefault();
if (단어.textContent[단어.textContent.length -1] === 입력창.value[0]){
결과창.textContent = '딩동댕';
단어.textContent = 입력창.value;
입력창.value = ''; //입력창을 비워주는 것
입력창.focus(); //커서가 자동으로 입력창에 있음
}else{
결과창.textContent = '땡!';
}
});

===

반복문
// while(true){
// var answer = prompt(word);
// if (word[word.length -1] === answer[0]){
// alert('딩동댕');
// word = answer;
// } else {
// alert('땡');
// }
// }