모던 자바스크립트 (5)

깨진알·2023년 12월 14일

JavaScript

목록 보기
15/21

자바스크립트의 유용한 내부 기능

1. 배열 메소드 I : forEach와 map

// forEach와 map
const memebers = ['A', 'B', 'C', 'D'];

for (let member of memebers) {
  console.log(`${member}님이 입장하였습니다.`);
};

// forEach I
memebers.forEach(function (memeber) {
  console.log(`${i} ${memeber}님이 입장하였습니다.`);
});

// arrow function
members.forEach((member) => {
  console.log(`${member}님이 입장하였습니다.`);
});

// forEach II (Index)
const firstNames = ['A', 'B', 'C', 'D'];
const lastNames = ['a', 'b', 'c', 'd'];

firstNames.forEach((firstName, i) => {
  console.log(`${lastNames[i]}${firstName}님이 입장하였습니다.`);
});

// forEach III (Array)
const firstNames = ['A', 'B', 'C', 'D'];
const lastNames = ['a', 'b', 'c', 'd'];

firstNames.forEach((firstName, i, arr) => {
  console.log(`${lastNames[i]${firstName}님이 입장하였습니다.`);
});

// map
// 메소드의 호출 결과로 새로운 배열을 호출한다.
const firstNames = ['A', 'B', 'C', 'D'];
const lastNames = ['a', 'b', 'c', 'd'];

const fullNames = firstNames.map((firstName, i) => {
  return lastNames[i] + firstName;

console.log(fullNames); // (4) ["aA", "bB", "cC", "dD"]
});

// arrow function (forEach는 리턴값이 없기 때문에 undefined 값을 출력한다.)
const fullNames = firstNames.map((firstName, i) => lastNames[i] + firstName);
  • forEach
    배열의 요스를 하나씩 살펴보면서 반복 작업을 하는 메소드이다. forEach 메소드는 첫 번째 아규먼트로 콜백 함수는 전달받는다. 콜백 함수의 파라미터에는 각각 배열의 요소, index, 메소드를 호출한 배열이 전달된다. forEach 메소드에는 파라미터 한 개가 무조건 작성되어야 한다.

  • map
    forEach와 비슷하게 배열의 요소를 하나씩 살펴보면서 반복 작업을 하는 메소드이다. 단, 첫 번째 아규먼트로 전달하는 콜백 함수가 매번 리턴하는 값들을 모아서 새로운 배열을 반들어 리턴하는 특징이 있다. map 메소드는 메소드의 호출 결과로 새로운 배열을 호출한다.

forEachmap 메소드는 최대 반복 횟수는 처음 호출할 때 그 당시 요소의 개수와 같다.

2. 배열 메소드 II : filter와 find

// filter와 find
// filter
const devices = [
  { name: 'GalaxyNote', brand: 'Samsung' },
  { name: 'MacbookPro', brand: 'Apple' },
  { name: 'iPad', brand: 'Apple' },
  { name: 'GalaxyWatch', brand: 'Samsung' },
  { name: 'iMac', brand: 'Apple' },
  { name: 'Gram', brand: 'LG' },
];
  
const apples = devices.filter((el) => el.brand === 'Apple');

console.log(apples); // (3) [{...}, {...}, {...}]

// find : 하나의 값만 찾고 싶을 때
const myLaptop = devices.find((el) => el.name === 'Gram');

console.log(myLaptop); // {name: "Gram", brand: "LG"}
  • filter
    filter 메소드는 배열의 요소를 하나씩 살펴보면서 콜백 함수가 리턴하는 조건과 일치하는 요소만 모아서 새로운 배열을 리턴하는 메소드이다.

  • find
    find 메소드는 filter 메소드와 비슷하게 동작하지만, 배열의 요소들을 반복하는 중에 콜백 함수가 리턴하는 조건과 일치하는 가장 첫 번째 요소를 리턴하고 반복을 종료하는 메소드이다.

3. 배열 메소드 III: some과 every

// some과 every
const numbers = [1, 3, 5, 7, 9];

// some: 조건을 만족하는 요소가 1개 이상 있는지
// 조건을 만족하는 요소를 찾는 순간 반복을 종료한다.
const someReturn = numbers.some((el) => el > 5);

// every: 모든 요소가 조건을 만족하는지
// 조건을 만족하지 않는 요소를 찾는 순간 반복을 종료한다.
// every: 조건을 만족하지 않는 요소가 1개 이상 있는지
const everyReturn = numbers.every((el) => el > 5);

console.log('some:', someReturn); // some: true
console.log('every:', everyReturn); // every: false

// 빈 배열
const numbers = [];
// some: false
// every: true
  • some
    some 메소드는 배열 안에 콜백 함수가 리턴하는 조건을 만족하는 요소가 1개 이상 있는지를 확인하는 메소드이다. 배열을 반복하면서 모든 요소가 콜백 함수가 리턴하는 조건을 만족하지 않는다면 false를 리턴하고, 배열을 반복하면서 콜백 함수가 리턴하는 조건을 만족하는 요소가 등장한다면 바로 true를 리턴하고 반복을 종료한다.

  • every
    every 메소드는 배열 안에 콜백 함수가 리턴하는 조건을 만족하지 않는 요소가 1개 이상 있는지를 확인하는 메소드이다. 배열을 반복하면서 모든 요소가 콜백 함수가 리턴하는 조건을 만족한다면 true를 리턴하고, 배열을 반복하면서 콜백 함수가 리턴하는 조건을 만족하지 않는 요소가 등장한다면 바로 false를 리턴하고 반복을 종료한다.

4. 배열 메소드 IV : reduce

// reduce
const numbers = [1, 2, 3, 4];

// acc : 누산기(Accumulator)를 의미한다. 
// el : 배열의 요소가 전달된다.
// i : 요소의 인덱스가 전달된다.
// arr : 메소드를 호출한 배열이 전달된다
numbers.reduce((acc, el, i, arr) => {
  return nextAccValue;
}, initialAccValue);

// ----------------------- //
const numbers = [1, 2, 3, 4];

const sumAll = numbers.reduce((acc, el, i) => {
  console.log(`${i}번 index의 요소로 콜백함수가 동작중입니다.`);
  console.log('acc:', acc);
  console.log('el:', el);
  
  return acc + el;
}, 0); // 처음 동작하는 콜백 함수에 acc에 전달된다.
// 만약 작성하지 않으면 배열의 0번 인덱스에 첫 번째 acc에 전달된다.

console.log('sumAll:', sumAll);
0번 index의 요소로 콜백함수가 동작중입니다.
acc: 0
el: 1
1번 index의 요소로 콜백함수가 동작중입니다.
acc: 1
el: 2
2번 index의 요소로 콜백함수가 동작중입니다.
acc: 3
el: 3
3번 index의 요소로 콜백함수가 동작중입니다.
acc: 6
el: 4
sumAll: 10

reduce 메소드는 누적값을 계산할 때 활용하는 조금 독특한 메소드이다. reduce 메소드는 일반적으로 두 개의 파라미터를 활용한다. 첫 번재는 반복동작할 콜백 함수이다. 매번 실행되는 콜백 함수의 리턴값이 다음에 동작할 콜백 함수의 첫 번째 파라미터로 전달된다. 결과적으로 마지막 콜백 함수가 리턴하는 값이 reduce 메소드의 최종 리턴값이 되는 것이다. 이 때 reduce 메소드의 두 번째 파라미터로 전달한 초기값이 첫 번째로 실행될 콜백 함수의 가장 첫 번째 파리미터로 전달되는 것이다.


5. sort, reverse

(1) sort 메소드

배열에서 sort 메소드를 활용하면 배열을 정렬할 수 있다. sort 메소드에 아무런 아규먼트도 전달하지 않을 때는 기본적으로 유니코드에 정의된 문자열 순서에 따라 정렬된다.

const letters = ['D', 'C', 'E', 'B', 'A'];
const numbers = [1, 10, 4, 21, 36000];

letters.sort();
numbers.sort();

console.log(letters); // (5) ["A", "B", "C", "D", "E"]
console.log(numbers); // (5) [1, 10, 21, 36000, 4]

numberssort 메소드를 사용한 것처럼, 숫자를 정렬할 때는 우리가 알고있는 오름차순이나 내림차순으로 정렬이 되지 않는다. 그럴 때에는 sort 메소드에 다음과 같은 콜백함수를 아규먼트로 작성해주면 된다.

const numbers = [1, 10, 4, 21, 36000];

// 오름차순 정렬
numbers.sort((a, b) => a - b);
console.log(numbers); // (5) [1, 4, 10, 21, 36000]

// 내림차순 정렬
numbers.sort((a, b) => b - a);
console.log(numbers); // (5) [36000, 21, 10, 4, 1]

sort 메소드를 사용할 때 한 가지 주의해야할 부분은 메소드를 실행하는 원본 배열의 요소들을 정렬한다는 점이다. 그래서 한 번 정렬하고 나면 정렬하기 전의 순서로 다시 되돌릴 수 없으니, 미리 다른 변수에 복사를 해두면 좋다.

(2) reverse 메소드

reverse 메소드는 말 그대로 배열의 순서를 뒤집어 주는 메소드이다. reverse 메소드는 별도의 파라미터가 존재하지 않기 때문에 단순히 메소드를 호출해주기만 하면 배열의 순서가 뒤집어진다. sort 메소드와 마찬가지로 원본 배열의 요소들을 뒤집어 버린다는 점도 알아두어야 한다.

const letters = ['a', 'c', 'b'];
const numbers = [421, 721, 353];

letters.reverse();
numbers.reverse();

console.log(letters); // (3) ["b", "c", "a"]
console.log(numbers); // (3) [353, 721, 421]

6. Map, Set

(1) Map

Map은 이름이 있는 데이터를 저장한다는 점에서 객체와 비슷하다. 하지만 할당연산자를 통해 값을 추가하고 점 표기법이나 대괄호 표기법으로 접근하는 일반 객체와 다르게 Map은 메소드를 통해서 값을 추가하거나 접근할 수 있다. new 키워드를 통해서 Map을 만들 수 있고 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 안의 모든 요소를 제거하는 메소드
  • map.size : 요소의 개수를 반환하는 프로퍼티 (메소드가 아니다. 배열의 length 프로퍼티와 같은 역할)
// Map 생성
const codeit = new Map();

// set 메소드
codeit.set('title', '문자열 key');
codeit.set(2017, '숫자형 key');
codeit.set(true, '불린형 key');

// get 메소드
console.log(codeit.get(2017)); // 숫자형 key
console.log(codeit.get(true)); // 불린형 key
console.log(codeit.get('title')); // 문자열 key

// has 메소드
console.log(codeit.has('title')); // true
console.log(codeit.has('name')); // false

// size 프로퍼티
console.log(codeit.size); // 3

// delete 메소드
codeit.delete(true);
console.log(codeit.get(true)); // undefined
console.log(codeit.size); // 2

// clear 메소드
codeit.clear();
console.log(codeit.get(2017)); // undefined
console.log(codeit.size); // 0

문자열과 심볼 값만 key(프로퍼티 네임)로 사용할 수 있는 일반 객체와는 다르게 Map 객체는 메소드를 통해 값을 다루기 때문에, 다양한 자료형을 key로 활용할 수 있다는 장점이 있다.

(2) Set

Set은 여러 개의 값을 순서대로 저장한다는 점에서 배열과 비슷하다. 하지만 배열의 메소드는 활용할 수 없고 Map과 비슷하게 Set만의 메소드를 통해서 값을 다루는 특징이 있다. Map과 마찬가지로 new 키우드로 Set을 만들 수 있고 Set 안의 여러 값들을 다룰 수 있다.

  • set.add(value) : 값을 추가하는 메소드. 메소드를 호출한 자리에는 추가된 값을 가진 Set 자신을 반환한다.
  • set.has(value) : Set 안에 값이 존재하면 true, 아니면 false를 반환하는 메소드
  • set.delete(value) : 값을 제거하는 메소드. 메소드를 호출한 자리에는 Set 내에 값이 있어서 제거에 성공하면 true, 아니면 false를 반환한다.
  • set.clear() : Set 안의 모든 요소를 제거하는 메소드
  • set.size : 요소의 개수를 반환하는 프로퍼티. (메소드가 아니다. 배열의 length 프로퍼티와 같은 역할)
// Set 생성
const members = new Set();

// add 메소드
members.add('영훈'); // Set(1) {"영훈"}
members.add('윤수'); // Set(2) {"영훈", "윤수"}
members.add('동욱'); // Set(3) {"영훈", "윤수", "동욱"}
members.add('태호'); // Set(4) {"영훈", "윤수", "동욱", "태호"}

// has 메소드
console.log(members.has('동욱')); // true
console.log(members.has('현승')); // false

// size 프로퍼티
console.log(members.size); // 4

// delete 메소드
members.delete('종훈'); // false
console.log(members.size); // 4
members.delete('태호'); // true
console.log(members.size); // 3

// clear 메소드
members.clear();
console.log(members.size); // 0

일반 객체는 프로퍼티 네임으로, Map은 get 메소드로, 그리고 배열은 index를 통해서 개별 값에 접근할 수 있다. 하지만 Set에는 개별 값에 바로 접근하는 방법이 없다.

// Set 생성
const members = new Set();

// add 메소드
members.add('영훈'); // Set(1) {"영훈"}
members.add('윤수'); // Set(2) {"영훈", "윤수"}
members.add('동욱'); // Set(3) {"영훈", "윤수", "동욱"}
members.add('태호'); // Set(4) {"영훈", "윤수", "동욱", "태호"}

for (const member of members) {
  console.log(member); // 영훈, 윤수, 동욱, 태호가 순서대로 한 줄 씩 콘솔에 출력됨.
}

그렇기 때문에 반복문을 통해서 전체요소를 한번에 다룰 때 반복되는 그 순간에 개별적으로 접근할 수가 있다. 이런 특징을 가지고도 Set이 유용하게 사용되는 경우가 있다. 바로, 중복을 허용하지 않는 값들을 모을 때이다. Set은 중복되는 값을 허용하지 않는 특징이 있다.

// Set 생성
const members = new Set();

// add 메소드
members.add('영훈'); // Set(1) {"영훈"}
members.add('윤수'); // Set(2) {"영훈", "윤수"}
members.add('영훈'); // Set(2) {"영훈", "윤수"}
members.add('영훈'); // Set(2) {"영훈", "윤수"}
members.add('동욱'); // Set(3) {"영훈", "윤수", "동욱"}
members.add('동욱'); // Set(3) {"영훈", "윤수", "동욱"}
members.add('동욱'); // Set(3) {"영훈", "윤수", "동욱"}
members.add('태호'); // Set(4) {"영훈", "윤수", "동욱", "태호"}
members.add('동욱'); // Set(4) {"영훈", "윤수", "동욱", "태호"}
members.add('태호'); // Set(4) {"영훈", "윤수", "동욱", "태호"}
members.add('태호'); // Set(4) {"영훈", "윤수", "동욱", "태호"}

최초에 추가된 순서를 유지하면서, 나중에 중복된 값을 추가하려고 하면 그 값은 무시하는 특징이 있다. 처음 Set을 생성할 때 아규먼트로 배열을 전달할 수도 있다. 이런 특징을 활용해서 배열 내에서 중복을 제거한 값들의 묶음을 만들 때 Set을 활용하기도 한다.

const numbers = [1, 3, 4, 3, 3, 3, 2, 1, 1, 1, 5, 5, 3, 2, 1, 4];
const uniqNumbers = new Set(numbers);

console.log(uniqNumbers); // Set(5) {1, 3, 4, 2, 5}
profile
프론트엔드 지식으로 가득찰 때까지

0개의 댓글