Python에는 for와 while이라는 반복문이 있고, 이 둘은 범위냐 조건이냐의 차이만 빼면 반복문이라는 기본 골자는 같은데, 이런 게 자바스크립트에도 당연히 있다. 라디오버튼 뺑뺑이 돌면서 얘가 뭘 체크했나 보는 것도 반복문의 일이기 때문.
그런데 이 반복문… Python처럼 심플하지 않아요…
for, for in, for of
See the Pen for, for in, for of by koreanraichu (@koreanraichu) on CodePen.
얘네들은 Pyhlogenic tree로 치자면 그 트리가 막 갈라지는 와중에도 진화적으로 매우 유사한 homolog이기 때문에 또이또이 쌤쌤임을 인정받은 애들… 맞는 비유인지는 모르겠지만, 자매나 형제같은 느낌이다. 그래서 형식 말고 크게 다를 건 없다.
let pokemon = ['김부추씨','김상추씨','김배추씨','김양상추씨','김양배추씨','김후추씨']
for (let i = 0;i < pokemon.length;i++) {
let p_tag = document.createElement('p')
p_tag.innerText = pokemon[i]
pokemon_div.appendChild(p_tag)
}
//for
for
let num_list = [806, 26, 607, 601, 752, 504, 485, 162, 885, 361, 309, 480, 401, 313, 771, 141, 9, 526, 390, 237]
for (let i in num_list) {
let p_tag = document.createElement('p')
if (num_list[i] % 4 == 0) {
p_tag.innerText = num_list[i]
for_in_div.appendChild(p_tag)
}
}
// for in
for in
for (let i of num_list) {
let p_tag = document.createElement('p')
if (i % 3 == 0) {
p_tag.innerText = i
for_of_div.appendChild(p_tag)
}
}
//for of
for of
각 소스에서 이 반복문이 하는 일은
- 포켓몬 리스트의 요소를 내용으로 하는 p태그를 생성하라
- 위에 있는 숫자 리스트에서 4의 배수를 p태그로 생성하라
- 위에 있는 숫자 리스트에서 3의 배수를 p태그로 생성하라
이렇게 세 개다. 그리고 세 반복문은 주어진 일을 하기 위해 각각 주어진 배열에 접근해 해당 요소를 가져와 p태그로 만들어서 내보내게 된다. for of는 파이썬으로 치자면 for i in (리스트)로 직접 접근하는 것으로, 저 경우 i에 들어가는 게 배열이 담고 있는 요소가 된다. DOM이면 DOM, 숫자면 숫자, 문자면 문자 이런 식. 반면 위의 두 반복문은 i 자체는 숫자라 인덱싱 절차가 따로 필요하다. 즉 for in이 for i in (리스트)면 나머지 둘은 for i in range(n)으로 인덱스 번호 만들어서 인덱싱 하는 것.
forEach
얘는 위에 셋과는 성격이 조금 다르다. Phylogenic tree로 치자면 쭉 내려가다가 마지막에 가지가 한번 갈라지고 그 다음에 for, for in, for of가 갈라지는 정도. 왜냐하면 얘는 배열에서 뭘 가져온다는 개념이 아니라 배열을 돌면서 주어진 함수를 실행하는 반복문이기 때문이다. 물론 for로 구현할 수 있는 건 forEach로도 구현할 수 있다.
See the Pen For and Foreach by koreanraichu (@koreanraichu) on CodePen.
여기서 for와 forEach의 차이점을 볼 수 있다.
let p_for = document.querySelectorAll('.for > p')
let p_forEach = document.querySelectorAll('.foreach > p')
// querySlectorAll은 배열로 가져온다
let number_list = ['일','이','삼']
for (let i = 0;i < p_for.length;i++) {
p_for[i].innerText = number_list[i]
}
//for
p_forEach.forEach(function(element, index){
element.innerText = number_list[index]
})
//forEach
아니 저거 저렇게 선택되는 줄 몰랐음… 아무튼… 위 코드가 하는 일은 div 안에 있는 p태그의 내용을 number_list에 있는 일, 이, 삼으로 바꾸는 것이다. (원문은 외국어) 둘 다 querySelectorAll()로 가져오기 때문에 가져왔을 때 상태는 배열이고, 배열 안에 p태그 세 개가 담겨 있기 때문에 for나 forEach를 사용해서 안에 있는 p태그의 내용을 바꿔줘야 한다.
for문은 말 그대로 위의 배열에서 i번째 요소를 num_list의 i번째 요소로 바꾸는 대단히 심플한 코드인데… forEach에 저거 뭡니까… 아… 저거는 요소와 인덱스로 함수 돌린다는 얘기인데, querySelectAll()로 가져온 배열을 순회하면서 배열이 담고 있는 요소(p태그)를 num_list[인덱스]의 요소로 채운다는 얘기다. 저 인덱스는 querySelectorAll()로 가져온 배열의 인덱스를 말한다. 아니 실화임.
See the Pen For and Foreach 2 by koreanraichu (@koreanraichu) on CodePen.
여기서는 for of와 forEach를 비교해보자.
let sqrt_n = document.querySelector(".sqrt")
let square_n = document.querySelector(".square")
let num_list = [1,2,3,4,5,6,7,8,9,10]
//sqrt: 제곱근(루트)
//square: 2제곱(3제곱은 cube)
for (let i of num_list) {
let p_tag = document.createElement('p')
p_tag.innerText = `sqrt ${i}: ${(i ** 0.5).toFixed(3)}`
sqrt_n.appendChild(p_tag)
}
// 리스트에 있는 수의 2제곱근을 출력(소수점 이하 3자리에서 반올림)
num_list.forEach(function(element){
let p_tag = document.createElement('p')
p_tag.innerText = element ** 2
square_n.appendChild(p_tag)
})
//리스트에 있는 수의 제곱을 출력
위 코드는 배열 안에 있는 수의 제곱근을 소수점 세자리까지 출력하는 코드이고, 아래 코드는 배열 안에 있는 수를 제곱해서 출력하는 코드이다. 아, 왜 **냐면 자바스크립트와 파이썬에서 ^는 XOR을 의미한다. 그래서 파이썬이나 자바스크립트로 2 ^ 2 하면 4가 아니라 0이 나온다. (XOR은 입력 두 개가 달라야 참임)
두 코드가 크게 다를 건 없다. 위 코드는 num_list에 있는 요소(숫자)를 가져와 0.5제곱(2루트)을 하고 innerText로 만든 다음 그걸 추가하는거고, 아래는 num_list를 순회하면서 안에 있는 요소(숫자)의 2승을 구하고 그걸 innerText로 만들어서 추가한다.
See the Pen For and Foreach 3 by koreanraichu (@koreanraichu) on CodePen.
for in과 forEach를 비교해보자.
let num_list = [1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16,17,18,19,20]
let num_list2 = [21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]
//아니 자바스크립트는 list(range()) 없나?
let odd_number = document.querySelector('.odd')
let even_number = document.querySelector('.even')
for (let i in num_list) {
let p_tag = document.createElement('p')
if (num_list[i] % 2 == 0) {
p_tag.innerText = `${num_list[i]} is even number`
even_number.appendChild(p_tag)
}
else {
p_tag.innerText = `${num_list[i]} is odd number`
odd_number.appendChild(p_tag)
}
}
num_list2.forEach(function(element){
let p_tag = document.createElement('p')
if (element % 2 == 0) {
p_tag.innerText = `${element} is even number`
even_number.appendChild(p_tag)
}
else {
p_tag.innerText = `${element} is odd number`
odd_number.appendChild(p_tag)
}
})
위 코드는 1~20까지의 배열에 있는 요소(숫자)가 짝수냐 홀수냐에 따라 다른 div에 추가한다. 그리고 아래 코드도 비슷한 일을 하는데, forEach는 21~40까지 있는 배열을 순회하면서 요소(숫자)에 조건문을 적용하고 각각의 div에 추가하게 된다.
See the Pen Untitled by koreanraichu (@koreanraichu) on CodePen.
const button = document.getElementById('button')
const print = document.querySelector('.print')
const choose = document.querySelectorAll('.pokemon')
button.addEventListener('click',(e)=>{
let question = ''
choose.forEach(function(element){
if (element.checked) {
if (element.value == 'grass') {
question = '풀타입 포켓몬인 이상해씨로 하겠느냐?'
}
else if (element.value == 'water') {
question = '물타입 포켓몬인 꼬부기로 하겠느냐?'
}
else if (element.value == 'fire') {
question = '불타입 포켓몬인 파이리로 하겠느냐?'
}
else {
question = '전기타입 포켓몬인 피카츄로 하겠느냐?'
}
print.innerText = question
}
})
})
for나 forEach를 사용하면 이런 식으로 동일한 클래스의 라디오버튼을 배열로 받아오고 순회하면서, 선택이 되었는지를 확인하고 선택된 라디오버튼의 값에 따라 다른 이벤트를 줄 수 있다.
Reply