안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
유사배열
- 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>`;
});
}