[자바스크립트] TIL8 : 반복문의 종류와 구조 / 객체의 특성과 배열의 요소 순회를 위한 반복문 활용
▣ 반복문(Loop)
반복문에는 아래와 같이 세 가지 정도의 종류가 있으며 겉보기에 구조가 다르지만, 일반적으로 사용되는 코딩 패턴은 모두 다 초기화, 조건식, 반복자 증가, 명령의 네 가지 구문을 공통적으로 포함하고 있습니다..
□ For 반복문
for ( <initializing>; <condition>; <increment> ) {
// <execution>
}
주로 사용하는 반복문 형태로 초기화, 조건식, 반복자 증가의 구문이 ( )안에 연속해서 들어가고, { } 블럭 안에는 명령 구문이 위치합니다. 코드의 실행은 먼저 초기화가 이루어진 다음, 조건식을 만족할 경우에 명령구문이 실행되고, 그 후에 반복자가 증가됩니다. 그런 다음 다시 조건식의 결과가 참인지 확인하여 참일 경우에 명령 구문도 한번 더 실행되는 순서로 진행되는데, 조건식을 만족하지 않을 때까지 계속됩니다. 참고로 반복자는 증가만 하는 것이 아니며 초기화와 조건식에 따라 다릅니다.
□ While 반복문
<initializing>
while ( <condition> ) {
// <execution>
// <increment>
}
{ } 블럭 밖에서 초기화가 이루어지고, ( ) 안의 조건식을 만족할 경우에 { } 블럭 내의 명령을 실행하며, 그런 다음에 반복자가 증가됩니다. 이때 반복자가 증가되는 시점은 명령의 실행 이전이 될 수도 있고 이후가 될 수도 있습니다.
□ Do While 반복문
<initializing>
do {
// <execution>
// <increment>
} while ( <condition> )
{ } 블럭 밖에서 초기화가 이루어지고, 일단 먼저 { } 블럭 내의 명령을 실행한 다음에, ( ) 안의 조건식을 만족할 경우 반복문이 계속 진행되고 그렇지 않을 경우에는 반복문이 더 이상 진행되지 않습니다. While 반복문과 마찬가지로 반복자가 증가되는 시점은 명령의 실행 이전이 될수도 있고 이후가 될 수도 있습니다.
□ 반복문 종류별 예시
/* For Loop */
for (let i = 0; i < 6; i++) {
console.log('Number ' + i);
}
/* While Loop */
let i = 0;
while (i < 6) {
console.log("Number " + i);
i++;
}
/* Do While Loop */
let j = 0;
do {
console.log("Number " + j);
j++;
} while (j < 6);
let k = 100;
do {
console.log("Number " + k);
k++;
} while (k < 6);
위와 같이 세 가지 종류의 반복문을 구조의 특성을 살려 간단히 구현해보면 아래와 같은 결과를 확인할 수 있습니다.

For 반복문과 While 반복문은 조건식을 먼저 진행하여 참인 조건하에서 명령을 실행하는 패턴이지만, Do While 반복문은 일단 처음에는 실행을 먼저 하고 다음 반복부터 조건식을 따르는 것에 유의하기 바랍니다.
□ continue 와 break 이용
/* General Loop */
for (let i = 0; i < 6; i++) {
if (i === 2) {
console.log("2 is my favorite number.");
}
console.log("Number " + i);
}
/* Loop with continue */
for (let i = 0; i < 6; i++) {
if (i === 2) {
console.log("2 is my favorite number.");
continue;
}
console.log("Number " + i);
}
/* Loop with break */
for (let i = 0; i < 6; i++) {
if (i === 2) {
console.log("2 is my favorite number.");
break;
}
console.log("Number " + i);
}
반복문을 제어하기 위해 { } 블럭 내에서는 주로 If 조건문을 많이 사용하며, 그 외에 반복문과 함께 자주 사용되는 코드에는 continue; 와 break; 가 있습니다.
아래의 결과에서 보다시피 continue; 코드는 이후의 { } 블럭 내 실행을 건너뛰고 다음 반복으로 넘어가라는 명령이고, break; 코드는 실행을 멈추고 반복문을 벗어나라는 명령입니다.

▣ 배열의 요소와 객체의 특성 순회
□ For Of 반복문
for (const <element> of <array>) {
// <execution>
}
일반적으로 배열의 길이('length' property)를 알고 있다면, For 반복문을 이용하여 모든 요소를 순회할 수 있습니다. 반면에 For Of 반복문을 사용하면 초기화, 배열의 길이를 포함하는 조건식, 반복자 증가의 구문을 작성하지 않고 간략하게 반복문을 나타낼 수 있어 편리합니다.
/**
* Traversing through Array's Elements
*/
const cars = ["Tesla", "Renault", "Volvo", "Volkswagen"];
/* For : statement */
for (let i = 0; i < cars.length; i++) {
console.log(cars[i]);
}
/* For Of : statement*/
for (const car of cars) {
console.log(car);
}
위의 코드의 실행 결과는 아래와 같습니다.

□ 반복문 내장 배열 메서드
한편, 배열 객체에는 배열의 모든 요소를 순회하면서 필요한 명령을 수행할 수 있도록 반복문이 내장된 배열 메서드들이 있습니다. 이 메서드들은 기본적으로 반복문을 포함하고 있기 때문에 복잡한 연산을 간단하게 나타낼 수 있어 유용합니다. 그리고 반복문이 내장된 배열 메서드들은 공통적으로 함수를 인자로 가집니다.
forEach(function ( <currentValue>, <index>, <array> ) {
// <execution>
});
배열 내의 요소들을 순회하면서 명령을 반복적으로 실행합니다. 기존의 For 반복문을 간략화한 형태라고 볼 수 있습니다.
▷ map()
const newArray = map(function ( <currentValue>, <index>, <array> ) {
// return <element> for newArray, after <execution>
});
배열 내의 요소들을 순회하면서 명령을 반복적으로 실행하되, 각 요소에 대한 결과 값들을 모두 모아 새로운 배열로 반환합니다. 즉 map() 메서드의 실행을 통해 반환되는 결과는 배열의 형태입니다.
▷ filter()
const newArray = filter(function ( <currentValue>, <index>, <array> ) {
// return <element> for newArray, if true
});
배열 내의 요소들을 순회하면서 조건식을 만족하는 요소들만 모아 새로운 배열로 반환합니다. 기능적으로 map()과 유사하지만 명령을 실행하느냐 아니면 참 또는 거짓을 판명하느냐의 차이가 있습니다.
▷ reduce()
const result = reduce(function ( <accumulator>, <currentValue>, <index>, <array> ) {
// return <accumulator> for result, after <execution>
}, <initialValue> );
사실상 앞서 설명한 반복문이 내장된 배열 메서드 모두를 아우를 수 있는 메서드입니다. 사용법이 복잡하고 까다로운 것 같지만 제대로 활용할 수 있게 된다면 정말 유용한 메서드입니다. 누산기(Accumulator)라는 개념이 적용되어 길이가 긴 배열 형태의 데이터를 대상으로 압축, 요약할 수 있는 명령(합계, 평균 구하기 등)을 쉽게 구현할 수 있습니다.
특히, 누산기의 초기값(initialValue)을 설정할 수 있는데, 예를 들어 0을 시작 값으로 설정하여 누적 갯수를 구하거나 혹은 빈 배열([ ])을 시작 값으로 설정하여 최종 결과를 배열의 형태로 반환할 수 있습니다.
초기값 설정은 메서드의 실행 결과를 변수에 담고자 할 때 발생할 수 있는 에러 또는 undefined를 방지합니다. 그리고 시작 값이 별도로 정해지지 않을 경우에는 대상이 되는 배열의 첫 번째 요소가 시작 값으로 설정됩니다.
□ 배열의 요소 순회 예시
/**
* Traversing through Array's Elements
*/
/* forEach() : method */
const cars = ["Tesla", "Renault", "Volvo", "Volkswagen"];
cars.forEach(function (car, index) {
console.log(`${index} : ${car}`);
});
/* map() : method */
const users = [
{ id: 1, name: "Pete" },
{ id: 2, name: "Jerry" },
{ id: 3, name: "Ethan" }
];
const ids = users.map(function (user) {
return user.id;
});
console.log(ids);
const names = users.map(function (user) {
return user.name;
});
console.log(names);
/* filter() : method */
const result = users.filter(function (user) {
return user.id < 3;
});
console.log(result);
/* reduce() : method */
const counter = users.reduce(function (acc, val) {
if (val.id < 3) {
return acc + 1;
}
return acc;
}, 0);
console.log(counter);
위의 코드와 아래의 실행 결과를 살펴보면, forEach() 를 이용하여 cars 배열의 모든 요소를 순회하면서 인덱스 값과 자동차 제조사를 콘솔에 출력하였고, map() 을 이용해서 users 배열 내의 모든 객체를 순회하면서 아이디 또는 이름을 각각 모아 배열로 반환하였으며, filter() 를 이용해서는 users 배열 내의 객체 중에서 아이디 값이 3보다 작은 경우의 객체만 골라 배열로 반환하였습니다. 마지막으로 reduce() 를 이용하여 users 배열 내의 객체 중에서 아이디 값이 3보다 작은 사용자들의 인원수를 구하여 결과로 반환하였습니다.

□ For In 반복문
for (const <property> in <object>) {
// <execution>
}
배열과 마찬가지로 객체 또한 모든 특성들의 갯수를 알고 있다면, For 반복문을 이용하여 순회할 수 있습니다. 반면에 For In 반복문을 사용하면 초기화, 특성의 갯수를 포함하는 조건식, 반복자 증가의 구문을 작성하지 않고 간략하게 반복문을 나타낼 수 있어 편리합니다.
※ 참고로 객체를 구성하고 있는 특성들의 개수를 알 수 있는 코드는 아래와 같습니다.
Object.keys( <object> ).length;
□ 객체의 특성 순회 예시
/**
* Traversing through Object's Properties
*/
const user = {
firstName: "John",
lastName: "Doe",
age: 30,
};
/* For : statement */
for (let i = 0; i < Object.keys(user).length; i++) {
console.log(`${Object.keys(user)[i]} : ${user[Object.keys(user)[i]]}`);
}
/* For In : statement */
for (const key in user) {
console.log(`${key} : ${user[key]}`);
}
위의 코드와 아래의 결과를 살펴보면, 객체의 특성을 순회할 때 For In 반복문이 For 반복문 보다 가독성이 높음을 파악할 수 있습니다.
