본문 바로가기
JavaScript/JavaScript

Javascript) 배열(3) (유사배열-Array.from, [...Array] / 배열반복처리-for..in문, for..of문, forEach() / map / filter / reduce)

by 박채니 2022. 5. 20.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


유사배열

- Array.prototype을 상속하지 않은 배열 객체

- index, length는 있지만 Array.prototype의 메소드를 사용할 수 없음

- getElementsByXXX, querySelectorAll의 리턴 객체

 

HTML 코드

<button onclick="test12();">유사배열</button>

 

Javascript 코드

<script>
function test12() {
    const buttons = document.getElementsByTagName("button");
    console.log(buttons);
}
</script>

prototype이 Array가 아닌 것을 확인할 수 있습니다.

유사배열이 아니라 진짜 배열이라면 prototype : Array로 확인됩니다.

 

 

Array.prototype 메소드 사용 시

console.log(buttons.pop()); // Uncaught TypeError: buttons.pop is not a function

"Uncaught TypeError: buttons.pop is not a function"와 같은 에러메세지가 출력되는 것을 확인할 수 있습니다.

 

 

유사배열 - 진짜 배열로 변환 ① 

Array.from()

const arr = Array.from(buttons);
console.log(arr);
console.log(arr.pop());

Array.from()으로 유사배열을 진짜 배열로 변환하니 prototype이 Array로 확인되며, Array.prototype의 메소드들을 사용할 수 있는 것을 확인할 수 있습니다.

 

유사배열 - 진짜 배열로 변환 ②

[...유사배열]

const arr = [...buttons];
console.log(arr);
console.log(arr.pop());

마찬가지로 prototype이 Array로 변환된 것을 확인할 수 있으며, Array.prototype의 메소드들을 사용할 수 있다는 것을 확인할 수 있습니다.

 


배열의 반복 처리

 

HTML 코드

<button onclick="test13();">반복처리</button>

 

Javascript 코드

 

일반 for문

function test13() {
    const arr = ['a', 'b', 'c'];

    // 일반 for문
    for(let i = 0; i < arr.length; i++) {
        console.log(i, arr[i]);
    }
}

일반 for문에서 index를 이용하여 배열의 원소들을 꺼내올 수 있습니다.

 

for-in문

- 열거 속성이 true인 요소 반환

- 배열 인덱스 반환

// for-in문
for(let i in arr) {
    console.log(i, arr[i]);
}

arr에서 꺼내온 i에는 원소가 아닌 index가 반환된 것을 확인할 수 있습니다.

꺼내온 index를 이용하여 원소를 가져올 수 있습니다.

 

for-of문

- 해당 객체가 iterator를 구현한 경우 사용 가능

- 배열은 내부적으로 iterator을 구현하므로 사용 가능

// for-of문
for(let ch of arr) {
    console.log(ch);
}

배열의 원소를 꺼내오는 것을 확인할 수 있습니다.

 

for-Each()

- 매 요소별로 콜백함수 호출

arr.forEach(function(ch, index, arr) {
    console.log(ch, index, arr);
});

forEach 함수에서 함수를 호출하여 원소, index, 배열을 꺼내올 수 있습니다.

콜백함수의 함수의 순서가 정해져있으므로 유의! (필요에 따라 생략 가능)

 


Map

- 현재 배열 요소에 특정 작업 후 변환된 값을 새 배열에 추가

 

HTML 코드

<button onclick="test14();">map</button>

 

Javascript 코드

 

function test14() {
    const arr = [1, 2, 3];
    const result = arr.map(function(n, index, arr) {
        console.log(n, index, arr);
    });
}

map 또한 forEach()처럼 콜백함수를 호출하며, 원소 / 인덱스 / 배열을 꺼내옵니다.

 

arr 원소의 제곱 수에 <mark>처리하기

const arr = [1, 2, 3];
const result = arr.map(function(n) {
    // console.log(n, index, arr);
    return `<mark>${n*n}</mark>`;
});
console.log(arr, result);

원본 배열인 arr에 대한 변화는 없는 것을 확인할 수 있으며, map을 통해 특정 작업(제곱,<mark>처리) 후 변환된 값에 대한 배열을 리턴하는 것을 확인할 수 있습니다.

 

forEach()를 이용하여 foo의 innerHTML 추가

<div id="foo"></div>

 

const arr = [1, 2, 3];
const result = arr.map(function(n) {
    // console.log(n, index, arr);
    return `<mark>${n*n}</mark>`;
});
// console.log(arr, result);
result.forEach(function(mark) {
    foo.innerHTML += (mark + " ");
});

 


filter

- 현재 배열 요소 중 조건에 맞는 요소만 추려내 새 배열에 추가

 

HTML 코드

<button onclick="test15();">filter</button>

 

Javascript

 

function test15() {
    const arr = [23, 2, 23, 54, 7, 8, 10, 77];
    const evens = arr.filter(function(n, index, arr) {
        console.log(n, index, arr);
    });
}

filter 또한 콜백함수를 호출하며 원소 / 인덱스 / 배열을 꺼내옵니다.

 

짝수인 수만 새 배열에 추가하기

const arr = [23, 2, 23, 54, 7, 8, 10, 77];
const evens = arr.filter(function(n, index, arr) {
    // console.log(n, index, arr);
    return n % 2 == 0;
});
console.log(evens);

n(원소) % 2 == 0인 수만 return하였기 때문에 evens에는 짝수의 원소들로 구성된 배열이 추가된 것을 확인할 수 있습니다.

 

숫자인 원소만 새 배열에 추가하기

const str = ["안녕", "34", "700원", "$35.5", "77", "4달라", 123, "2밤"];
const nums = str.filter(function(str){
    return !isNaN(Number(str));
}).map(function(str){
    return Number(str);
});

console.log(str, nums);

filter()를 이용하여 str배열의 원소를 Number() 타입으로 변환하였을 때 NaN이 아닌 원소를 가진 새 배열을 추가하였으며

(이 때 NaN 여부를 확인하는 isNaN()함수를 이용!)

해당 배열에서 map()을 이용하여 추려낸 원소들을 Number()를 이용해 Number타입으로 변환한 원소를 가진 배열을 추가하여 순수 숫자들로 구성된 배열을 완성하였습니다.

 


reduce(콜백함수, 초기값)

- 모든 요소를 대상으로 특정 작업 후 하나의 값(객체)을 반환

 

HTML 코드

<button onclick="test16();">reduce</button>

 

Javascript 코드

function test16() {
    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    const sum = arr.reduce(function(agg, n, index, arr) {
        console.log(agg, n, index, arr);
        return agg + n;
    }, 0);
    console.log(sum);
}

reduce()도 콜백함수를 호출하며, 누적 수 / 원소 / 인덱스 / 배열을 꺼내옵니다.

따라서 누적 수를 호출해주기 위해 return에 agg + n을 해주었습니다.

 

또한, 초기값을 설정할 수 있는데 초기값을 0으로 설정하니 첫번째 턴에서 원소 1에 대해 콜백함수를 실행하였을 때 설정해준 초기값이 넘어온 것을 확인할 수 있습니다.

첫번째 턴) 0 + 1 실행 → 결과값 1이 agg(누적)로 넘어감

두번째 턴) 1 + 2 실행 → 결과값 2가 agg(누적)로 넘어감

...

...

55 출력

위와 같은 흐름을 가지고 원소들의 합을 구할 수 있었습니다.

 

map과 filter와는 다르게 배열을 리턴하는 것이 아닌 단 하나의 값(혹은 객체)를 리턴하는 것을 확인할 수 있습니다.

※ 초기값을 생략한다면 배열의 첫번째 원소가 세팅!!!

 

reduce를 map처럼 사용해보기

// map처럼 사용
console.log(arr.reduce(function(ar, n, index) {
    ar.push(n*n);
    console.log(ar, n);
    return ar;
}, []));

초기값을 [] 배열로 주어 배열을 리턴해줄 수도 있습니다.

 

reduce를 filter처럼 사용해보기

// filter처럼 사용
console.log(
    arr.reduce(function(ar, n, index) {
        n % 2 == 0 && ar.push(n);
        return ar;
    }, []));

짧은 조건문을 이용하여 n이 짝수라면 ar 배열에 n을 추가해주었습니다.

마찬가지로 초기값을 [] 배열로 주었기 때문에 하나의 배열을 리턴해줍니다.

 

 

@실습 - 음료

- #drink 하위에 음료 목록을 모두 읽어와서 대문자로 변환

- 오름차순 정렬 후 다시 #drink하위에 추가

 

HTML 코드

<button onclick="test17();">@실습문제 - 음료</button>
<ul id="drink">
    <li>juice</li>
    <li>coffee</li>
    <li>cocktail</li>
    <li>beer</li>
    <li>whisky</li>
</ul>

 

Javascript 코드

function test17() {
    const list = [...document.querySelectorAll("#drink li")];

    const drinks = list.map(function(drink) {
        return drink.innerHTML.toUpperCase();
    }).sort().forEach(function(finalDrink) {
        drink.innerHTML += `<li>${finalDrink}</li>`;
    });
}