목차
배열
배열 메소드
맵 셋
iterable 객체
구조분해할당
배열
- 배열 끝에 무언가를 해주는 메서드
* 기존 인덱스를 유지하기 때문에 빠르다
Pop : 끝 요소를 제거하고 제거한 요소를 반환 (스택에 사용)
Push : 맨 끝에 요소 추가
- 배열 앞에 무언가를 해주는 메서드
* 전체 인덱스의 변경이 있기 때문에 느리다
Shift : 제일 앞 요소 제거한 뒤 반환, 남아있는 요소를 하나씩 민다 (큐에 사용)
Unshift : 배열 앞에 요소를 추가
let fruits = ["사과"];
fruits.push("오렌지", "배");
fruits.unshift("파인애플", "레몬");
// ["파인애플", "레몬", "사과", "오렌지", "배"]
- 배열은 순서가 있는 자료의 컬렉션임. 객체처럼 다루는 경우 최적화 기법이 적용되지 않아 배열의 장점이 사라짐.
아래와 같은 사용은 지양하자.
arr.test = 5 같이 숫자가 아닌 값을 프로퍼티 키로 사용하는 경우
arr[0]과 arr[1000]만 추가하고 그사이에 아무런 요소도 없는 경우
arr[1000], arr[999]같이 요소를 역순으로 채우는 경우
- 배열을 순회할 수 있는 방법은 아래와 같다.
for of는 인덱스가 아닌 배열의 값으로 순회하는 것 (파이썬의 for in 느낌)
let fruits = ["사과", "오렌지", "자두"];
for (let i = 0; i < fruits.length; i++) {
alert( arr[i] );
}
// 배열 요소를 대상으로 반복 작업을 수행합니다.
for (let fruit of fruits) {
alert( fruit );
}
for in은 모든 프로퍼티를 대상으로 순회한다. 따라서 키가 프로퍼티인 경우에도 순회한다. 따라서 느리기 때문에 지양하자!
배열 메서드
- Splice
칼과 같이 요소를 자유자재로 다루어, 요소 추가/삭제/교체를 가능하게 함
삭제된 요소로 구성된 배열을 반환
arr.splice(index[, deleteCount, elem1, ..., elemN])
index : 조작할 첫 번째 요소
deleteCount : 제거하고자 하는 요소의 개수
elem : 배열에 추가할 요소
let arr = ["I", "study", "JavaScript", "right", "now"];
// 처음(0) 세 개(3)의 요소를 지우고, 이 자리를 다른 요소로 대체합니다.
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // now ["Let's", "dance", "right", "now"]
- Slice
arr.slice([start], [end])
start 인덱스부터 end 인덱스까지 요소를 복사한 새로운 배열을 반환
- Concat
배열을 합쳐 새로운 배열을 만들고 싶을 때
객체가 합쳐질 때는 구조 분해가 되지 않고 통째로 객체가 넘겨진다.
(다만 Symbol.isConcatSpreadable을 사용할 경우엔 객체를 배열처럼 취급해, 객체의 값이 넘겨짐)
let arr = [1, 2];
let arrayLike = {
0: "something",
1: "else",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else
- Foreach
배열 요소에 반복작업을 하고싶을 때 사용
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} is at index ${index} in ${array}`);
});
- 배열 탐색 (indexOf includes find filter)
arr.indexOf(item, from) : 발견하면 item이 있는 인덱스를 반환, 없으면 -1
arr.lastIndexOf(item, from) : 검색을 끝에서부터 실행
arr.includes(item, from) : item을 발견하면 true를 반환
(*참고로 완전 항등 연산자(===)로 비교를 수행한다.)
arr.find
배열안에 특정 요소에 부합한 객체를 찾고 싶을 때 사용
함수의 반환값을 true로 만드는 하나의 요소만 찾음
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
let user = users.find(item => item.id == 1);
alert(user.name); // John
arr.findIndex 는 동일한 기능을 하나, 조건에 맞는 요소가 아닌 요소의 인덱스를 반환한다.
arr.filter
함수의 반환값을 true로 만드는 여러개의 요소가 있을때, 해당 요소의 배열을 반환
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
// 앞쪽 사용자 두 명을 반환합니다.
let someUsers = users.filter(item => item.id < 3);
alert(someUsers.length); // 2
- 배열 변형 (map sort reverse split join reduce)
Map
배열 요소 전체를 대상으로 특정 배열을 반환
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
Sort
배열 자체가 변형
또한 숫자를 정렬하고 싶을 때, 해당 숫자는 문자열처럼 인식되어 정렬이 되기 때문에
특정 정렬 알고리즘을 넣어주어야 한다!
function compareNumeric(a, b) {
if (a > b) return 1;
if (a == b) return 0;
if (a < b) return -1;
}
let arr = [ 1, 2, 15 ];
arr.sort(compareNumeric);
alert(arr); // 1, 2, 15
Reverse
역순 정렬
Split
해당 구분자를 통해 문자열을 끊어주고 싶을 때
배열의 길이를 제할 할 수 있다
let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2);
alert(arr); // Bilbo, Gandalf
Join
split과 반대로 배열의 요소들을 이어주는 역할
let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str = arr.join(';'); // 배열 요소 모두를 ;를 사용해 하나의 문자열로 합칩니다.
alert( str ); // Bilbo;Gandalf;Nazgul
Reduce
배열을 가지고 한 가지의 결과값을 도출하고 싶을 때 사용
함수가 호출될 때마다 결과값이 누적되어 다음 계산에 사용됨
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((sum, current) => sum + current, 0);
alert(result); // 15
배열 여부
배열인지 아닌지는 typeof()가 아닌 .isArray()로 정확하게 판별할 수 있따!
배열은 독립된 자료형이 아닌 객체로 취급되기 때문이다.
Iterable 객체
iterable한 객체 == 반복가능한 객체 == 배열 == for of 적용이 가능한 배열이 아닌 객체
Symbol.iterator
이터러블 하게 만들려면, 객체에 Symbol.iterator라는 특수내장심볼을 메서드에 추가해주면 된다.
아래에서는 range에 iterable한 객체를 추가하고, next()라는 메서드로 순회가능하도록 해줌으로써
배열이 아닌 객체를 iterable하게 만들어주었다.
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
for (let num of range) {
alert(num); // 1, then 2, 3, 4, 5
}
이터러블 객체 vs 유사배열
이터러블 객체: Symbol.iterator가 구현된 객체, for of를 사용
유사배열 : 인덱스, length 프로퍼티가 있는 '배열처럼 보이는 객체'
아래는 유사배열이지만 이터러블 객체가 아니다.
let arrayLike = { // 인덱스와 length프로퍼티가 있음 => 유사 배열
0: "Hello",
1: "World",
length: 2
};
// Symbol.iterator가 없으므로 에러 발생
for (let item of arrayLike) {}
Array.from()
이터러블이나 유사배열을 진짜 배열로 만들어준다!
해당 메소드를 통해 배열메소드를 적용할 수 있다.
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike); // (*)
alert(arr.pop()); // World (메서드가 제대로 동작합니다.)
아래와 같이 문자열을 대상으로 하나하나 받아와 배열로 정해줄 수도 있다.
let str = '𝒳😂';
// str를 분해해 글자가 담긴 배열로 만듦
let chars = Array.from(str);
alert(chars[0]); // 𝒳
alert(chars[1]); // 😂
맵/셋
맵 Map
키가 있다. 하지만 키에 다양한 자료형(객체도 가능)을 허용한다.
또한 set을 할 때마다 자기자신을 호출하기 때문에 체이닝을 허용한다.
- new Map() – 맵을 만듭니다.
- map.set(key, value) – key를 이용해 value를 저장합니다.
- map.get(key) – key에 해당하는 값을 반환합니다. key가 존재하지 않으면 undefined를 반환합니다.
- map.has(key) – key가 존재하면 true, 존재하지 않으면 false를 반환합니다.
- map.delete(key) – key에 해당하는 값을 삭제합니다.
- map.clear() – 맵 안의 모든 요소를 제거합니다.
- map.size – 요소의 개수를 반환합니다.
맵에서 반복작업
map.keys() : 각 요소의 키를 모은 이터러블 객체 반환
map.values() : 각 요소의 값을 모은 이터러블 객체 반환
map.entries() : 각 요소의 [키, 값]을 모은 이터러블 객체 반환
Object.entries : 객체 -> 맵
let obj = {
name: "John",
age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John
Object.fromEntries : 맵 -> 객체
Object.entries에서 반환하는 [키, 값] 형태는 객체용 이터러블을 위한 아주 좋은 형태를 띈다!
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);
let obj = Object.fromEntries(map.entries()); // 맵을 일반 객체로 변환 (*)
// 맵이 객체가 되었습니다!
// obj = { banana: 1, orange: 2, meat: 4 }
alert(obj.orange); // 2
셋 Set
중복을 허용하지 않는 값을 저장. 키는 없다!
- new Set(iterable) – 셋을 만듭니다. 이터러블 객체를 전달받으면(대개 배열을 전달받음) 그 안의 값을 복사해 셋에 넣어줍니다.
- set.add(value) – 값을 추가하고 셋 자신을 반환합니다.
- set.delete(value) – 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 true, 아니면 false를 반환합니다.
- set.has(value) – 셋 내에 값이 존재하면 true, 아니면 false를 반환합니다.
- set.clear() – 셋을 비웁니다.
- set.size – 셋에 몇 개의 값이 있는지 세줍니다.
Object.keys values entries
순회할 수 있는 위의 메소드는 Map, set, array에 사용가능하다.
객체에는 조금 다른 순회 메소드를 사용해야한다. 차이점은 아래와 같다.
1) map.keys() 호출 vs Object.keys() 호출
2) 이터러블 객체를 반환 vs 진짜 배열을 반환
아래와 같이 객체에 fromEntries를 이용해 객체에 배열용 메소드를 사용할 수 있다.
let prices = {
banana: 1,
orange: 2,
meat: 4,
};
let doublePrices = Object.fromEntries(
// 객체를 배열로 변환해서 배열 전용 메서드인 map을 적용하고 fromEntries를 사용해 배열을 다시 객체로 되돌립니다.
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
alert(doublePrices.meat); // 8
구조 분해 할당
배열 분해
아래와 같이 다양한 할당 가능한 값으로 배열을 분해할 수 있다.
// 두 번째 요소는 필요하지 않음
let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert( title ); // Consul
let user = {};
[user.name, user.surname] = "Bora Lee".split(' ');
alert(user.name); // Bora
또한 이를 이용해 변수를 교환할 때 쉽게 만들 수 있다.
let guest = "Jane";
let admin = "Pete";
// 변수 guest엔 Pete, 변수 admin엔 Jane이 저장되도록 값을 교환함
[guest, admin] = [admin, guest];
나머지 요소
몇개만 찾아오고 나머지는 한 데 모아서 저장하고 싶을 때
let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert(name1); // Julius
alert(name2); // Caesar
// `rest`는 배열입니다.
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
객체 분해
해당 분해를 통해 객체의 특정 프로퍼티만 뽑아올 수 있다.
: (콜론)으로 객체의 프로퍼티를 뒤의 변수에 저장
= (할당)으로 해당 값이 없을 때의 기본값을 지정
let options = {
title: "Menu"
};
let {width: w = 100, height: h = 200, title} = options;
alert(title); // Menu
alert(w); // 100
alert(h); // 200
아래와 같이 객체에서 특정 프로퍼티를 뽑아오고, 나머지는 객체로 취급해줄 수도 있다.
let options = {
title: "Menu",
height: 200,
width: 100
};
// title = 이름이 title인 프로퍼티
// rest = 나머지 프로퍼티들
let {title, ...rest} = options;
// title엔 "Menu", rest엔 {height: 200, width: 100}이 할당됩니다.
alert(rest.height); // 200
alert(rest.width); // 100
!!참고로 let을 이용하고 싶다면, ()을 이용해
js가 {}를 코드블록으로 인식해 할당해주지 않는 오점을 방지해주자.
let title, width, height;
// 에러가 발생하지 않습니다.
({title, width, height} = {title: "Menu", width: 200, height: 100});
alert( title ); // Menu
중첩 구조 분해
아래와 같이 복잡한 형태의 객체도 중첩해서 구조를 분해시킴으로써
더 편리하게 변수를 관리할 수 있다.
let options = {
size: {
width: 100,
height: 200
},
items: ["Cake", "Donut"],
extra: true
};
// 코드를 여러 줄에 걸쳐 작성해 의도하는 바를 명확히 드러냄
let {
size: { // size는 여기,
width,
height
},
items: [item1, item2], // items는 여기에 할당함
title = "Menu" // 분해하려는 객체에 title 프로퍼티가 없으므로 기본값을 사용함
} = options;
alert(title); // Menu
alert(width); // 100
alert(height); // 200
alert(item1); // Cake
alert(item2); // Donut
매개변수에 구조분해 적용하기
아래와 같이 인자로 여러개 복잡하게 넘겨주어야 할 때는,
매개변수를 객체로 관리해 넘겨줌으로써 함수에서 매개변수를 구조분해해서
더 효과적으로 관리할 수 있도록 할 수 있다.
또한 기본으로 함수의 매개변수로 객체를 할당해주어야하기 때문에
전체적으로 매개변수를 객체로 초기화해주었다. -> {} = {}
function showMenu({ title = "Menu", width = 100, height = 200 } = {}) {
alert( `${title} ${width} ${height}` );
}
showMenu(); // Menu 100 200
'Web > javascript' 카테고리의 다른 글
[javascript] 동기식 언어인 javascript가 통신을 하는 방법 (0) | 2023.06.04 |
---|---|
[Javascript] JS의 함수를 잘 활용하고 있나요? - JS 함수에 숨겨진 기능 톺아보기 (0) | 2023.05.18 |
[JS기본] 객체의 모든 것 / 프로퍼티, 생성자함수, this와 메소드, 옵셔널 체이닝 (1) | 2023.04.23 |
[JS 기본] 함수선언문 VS 함수표현식 / 콜백함수, 화살표함수 친해지기 (0) | 2023.04.10 |
[JS 기본] IF문과 논리연산자에 숨겨진 기능 (0) | 2023.04.10 |