본문 바로가기
Developer/TIL

[TIL] 250327목 (isNaN, Number.isNaN / split, splice, slice / reduce / map vs reduce)

by 청량리 물냉면 2025. 3. 27.
반응형

isNaN, Number.isNaN

isNaN(value)

  • 매개변수를 Number(value)로 변환 후 NaN인지 검사함.
  • 숫자로 변환할 수 없는 문자열을 넣으면 Number(value)가 NaN이 되므로 true를 반환.
  • 예제
isNaN('hello'); // true (Number('hello') → NaN)
isNaN(undefined); // true (Number(undefined) → NaN)
isNaN('123'); // false (Number('123') → 123)
isNaN({}); // true (Number({}) → NaN)
isNaN(' '); // false (Number(' ') → 0)
  • 타입스크립트에서의 문제점
    • isNaN(value: number): boolean으로 타입이 지정되어 있기 때문에, string을 넣으면 타입 오류 발생.
    • 하지만 JavaScript에서 isNaN()은 문자열도 암묵적으로 Number() 변환을 시도하기 때문에 타입 안정성이 떨어짐.

 

Number.isNaN(value)

  • 매개변수를 Number(value)로 변환하지 않고 그대로 NaN인지 검사함.
  • 즉, 오직 NaN 값만 true를 반환.
  • 예제
Number.isNaN('hello'); // false ('hello'는 NaN이 아님)
Number.isNaN(undefined); // false (undefined는 NaN이 아님)
Number.isNaN(NaN); // true (NaN은 NaN이 맞음)
Number.isNaN(123); // false (숫자는 NaN이 아님)
Number.isNaN('123'); // false ('123'은 NaN이 아님)
  • 타입스크립트에서의 장점:
    • Number.isNaN(value: unknown): boolean → unknown을 받기 때문에 어떤 타입이든 허용됨.
    • 값이 NaN인지 정확히 판별 가능.

✨ 결론

  • isNaN(value): 값을 숫자로 변환 후 NaN인지 검사 (의도하지 않은 변환 문제 발생 가능).
  • Number.isNaN(value): 그 값 자체가 NaN인지 직접 검사 (더 엄격하고 타입 안정적).

따라서, 실무에서는 Number.isNaN(value)를 쓰는 것이 더 안전하다!


split(), splice(), slice() 비교

메서드  사용 대상 역할  원본 변경 여부
split() 문자열 구분자로 나누어 배열로 변환 ❌ 변경 안 함
splice() 배열 요소 추가, 삭제, 교체 ✅ 변경됨
slice() 배열 & 문자열 일부 요소/문자만 가져옴 ❌ 변경 안 함

 

✅ split() (문자열을 배열로 변환)

문자열에서 특정 구분자로 나누고 싶을 때 사용

const str = "apple,banana,grape";
const result = str.split(","); // 쉼표(,)를 기준으로 분리
console.log(result); // ["apple", "banana", "grape"]
console.log(str); // "apple,banana,grape" (원본 변경 없음)
  • 구분자를 기준으로 문자열을 나눔
  • 결과는 배열(Array)
  • 원본 문자열 변경 없음(immutable)

 

✅ splice() (배열에서 요소 추가/삭제/교체)

배열의 요소를 제거하거나 새로운 요소를 추가할 때 사용

const arr = ["apple", "banana", "grape"];
arr.splice(1, 1, "orange"); // 1번 인덱스부터 1개 삭제 후 "orange" 추가
console.log(arr); // ["apple", "orange", "grape"]
  • 첫 번째 인자: 시작 인덱스
  • 두 번째 인자: 삭제할 요소 개수
  • 세 번째 이후 인자: 추가할 요소
  • 원본 배열이 변경됨(mutable)

 

✅ slice() (배열/문자열 일부 추출)

배열이나 문자열에서 일부만 복사해서 새로운 배열/문자열을 반환

const fruits = ["apple", "banana", "grape", "orange"];
const slicedFruits = fruits.slice(1, 3); // 1번부터 3번 이전까지(1,2) 복사
console.log(slicedFruits); // ["banana", "grape"]
console.log(fruits); // ["apple", "banana", "grape", "orange"] (원본 변경 없음)
const str = "Hello World";
const slicedStr = str.slice(0, 5); // 0번부터 5번 이전까지("Hello")
console.log(slicedStr); // "Hello"
console.log(str); // "Hello World" (원본 변경 없음)
  • 첫 번째 인자: 시작 인덱스
  • 두 번째 인자(선택적): 종료 인덱스(포함되지 않음)
  • 원본 데이터 변경 없음(immutable)

 

💡 어떤 상황에서 사용하면 될까?

  • 문자열을 나누고 싶다면?split()
  • 배열에서 요소를 삭제하거나 추가해야 한다면?splice()
  • 배열/문자열의 일부만 복사하고 싶다면?slice()

가장 큰 차이점

  • split(): 문자열 → 배열 변환
  • splice(): 배열 조작(삭제/추가/교체, 원본 변경)
  • slice(): 일부 요소/문자만 가져오기(원본 유지)

 

reduce()map()에서 return을 사용하는 이유

  • reduce()map()은 배열을 변형하거나 새로운 값을 생성하는 메서드이므로, 각 콜백 함수에서 return을 사용하여 원하는 값을 반환해야 한다.
  • {}를 사용하기 위해서는 return이 반드시 필요하다.

 

reduce()의 다양한 활용 예제

reduce()는 배열을 하나의 값으로 축약할 때 사용된다.
✔️ 누적 연산, 변형, 그룹화 등 다양한 용도로 활용 가능하다

 

✅ 1. 배열 숫자 합 구하기 (기본적인 reduce() 활용)

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15

✔️ acc(누적값) 초기값을 0으로 설정 → 배열의 모든 값을 더함.

 

✅ 2. 최대값 찾기

const numbers = [3, 7, 2, 8, 5];
const max = numbers.reduce((acc, num) => (num > acc ? num : acc), numbers[0]);
console.log(max); // 8

✔️ num > acc이면 새로운 최대값을 acc로 업데이트.

 

✅ 3. 객체 배열에서 특정 값 합산하기

const orders = [
{ item: "Apple", price: 3, quantity: 2 },
{ item: "Banana", price: 1, quantity: 5 },
{ item: "Orange", price: 2, quantity: 4 }
];
const totalPrice = orders.reduce((acc, order) => acc + order.price * order.quantity, 0);
console.log(totalPrice); // 19

✔️ 각 아이템의 price * quantity를 계산 후 전체 합산.

 

✅ 4. 배열의 중복 요소 개수 세기 (빈도수 계산)

const fruits = ["apple", "banana", "apple", "orange", "banana", "banana"];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(count);
// { apple: 2, banana: 3, orange: 1 }

✔️ acc를 객체로 활용하여 각 과일의 등장 횟수를 카운트.

 

✅ 5. 중첩 배열(flatten) 펼치기

const nestedArray = [[1, 2], [3, 4], [5, 6]];
const flattened = nestedArray.reduce((acc, arr) => acc.concat(arr), []);
console.log(flattened); // [1, 2, 3, 4, 5, 6]

✔️ concat()을 이용해 중첩 배열을 단일 배열로 변환.

 

✅ 6. 문자열 문자 개수 카운트

const sentence = "hello world";
const charCount = sentence.split("").reduce((acc, char) => {
if (char !== " ") acc[char] = (acc[char] || 0) + 1;
return acc;
}, {});
console.log(charCount);
// { h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1 }

✔️ 문자열을 split("")으로 배열로 변환 후, 각 문자의 개수를 카운트.

 

✅ 7. 배열의 특정 조건 필터링 (map + filter 역할 대체)

const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.reduce((acc, num) => {
if (num % 2 === 0) acc.push(num);
return acc;
}, []);
console.log(evenNumbers); // [2, 4, 6]

✔️ reduce()만으로 filter()와 같은 기능 구현 가능.

 

🎯 정리

용도 설명
누적 연산 합, 곱, 최대값, 최소값 찾기
배열 변환 map(), filter() 대체
데이터 그룹화 중복 요소 개수 카운트
배열 평탄화 중첩 배열을 1차원 배열로 변환

 

결론

  • reduce()는 배열을 하나의 값으로 축약하는 강력한 도구
  • map(), filter(), forEach()로 해결할 수 있는 것도 있지만, 특정 상황에서는 reduce()가 더 효율적이고 가독성이 좋다

 

map() vs reduce()

✅ map() → 각 요소를 변환하여 새로운 배열 반환

🧐 return을 반드시 써야 하는 이유?
→ map()은 배열의 각 요소를 변환한 후 새로운 배열을 반환하기 때문!

const numbers = [1, 2, 3, 4];
const squared = numbers.map(num => num * num); // 각 요소를 제곱
console.log(squared); // [1, 4, 9, 16]

📌 특징

  1. 기존 배열을 변경하지 않고, 변형된 새 배열을 반환.
  2. 반환값이 없으면(return 생략) undefined가 들어간 배열이 생성됨.
    const result = numbers.map(num => { num * num }); // 중괄호 {} 사용 시 return 필요
    console.log(result); // [undefined, undefined, undefined, undefined]
  3. ❌ return 생략 시:

💡 즉, map()을 사용할 때는 반드시 return을 통해 변환된 값을 반환해야 함.

 

 

✅ reduce() → 배열을 하나의 값으로 축약

🧐 return을 반드시 써야 하는 이유?
→ reduce()는 이전 콜백 결과를 누적하여 최종적으로 단일 값을 반환하기 때문

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 10

📌 특징

  1. acc(누적값)을 계속 업데이트하면서 최종 결과를 만듦.
  2. 반환값이 없으면(return 생략) undefined가 누적됨.
    const result = numbers.reduce((acc, num) => { acc + num }, 0);
    console.log(result); // undefined (acc에 아무것도 누적되지 않음)
  3. ❌ return 생략 시:

💡 즉, reduce()에서는 return을 사용해 반드시 누적할 값을 반환해야 함.

 

🎯 map() vs reduce() 차이점 정리

메서드 목적  return 필요 여부 반환값
map() 배열 변환 ✅ 필수 (새 배열 생성) 변형된 새로운 배열
reduce() 배열을 하나의 값으로 축약 ✅ 필수 (누적값 업데이트) 최종 단일 값

 

🚀 결론

  • map()은 변형된 값을 새 배열로 반환해야 하므로 return이 필요함
  • reduce()는 누적값을 업데이트하여 최종 결과를 반환해야 하므로 return이 필요함
  • 💡 return을 생략하면 undefined가 들어가거나 연산이 제대로 수행되지 않음
반응형