filter 함수, JS에서 파라미터의 규칙
Q1.
어떤 배열 item이 있다고 하자.
const totalSurvived=item.filter(heftychonk=>heftychonk.survived).length;
이렇게 filter 함수를 쓸 수 있는 이유는 뭐지?
원래 filter 함수를 쓰기 위해서는, item.filter((v,i)=>v.survived).length 이런 식 아니였나?
ChatGPT의 말:
좋은 질문이에요! JavaScript에서 filter 함수의 동작과 함께 작성하신 코드의 차이를 이해하면 더 나은 이해가 될 거예요. 하나씩 살펴보겠습니다.
1. filter 함수의 기본 동작
Array.prototype.filter 함수는 배열을 순회하면서 조건을 만족하는 요소만 새로운 배열에 포함시키는 함수입니다. 이 함수는 다음과 같은 형식으로 콜백 함수를 받습니다:
array.filter((value, index, array) => {
return 조건; // true일 경우 유지, false일 경우 제외
});
filter 함수의 콜백 함수는 다음 세 가지 매개변수를 받을 수 있습니다:
- value: 현재 순회 중인 배열의 값
- index: 현재 순회의 인덱스 (선택 사항)
- array: 현재 배열 자체 (선택 사항)
2. 질문하신 코드의 간단한 작성
질문에서 보신 이 코드:
const totalSurvived = item.filter(heftychonk => heftychonk.survived).length;
filter의 콜백 함수로 전달된 부분을 보면:
const totalSurvived = item.filter(heftychonk => heftychonk.survived).length;
이 코드는 축약 표현입니다. 화살표 함수(arrow function)를 사용하면서 매개변수(heftychonk)가 하나일 경우에는 괄호를 생략할 수 있습니다. 또한 함수 본문이 단일 표현식인 경우에는 중괄호 {}와 return 키워드도 생략할 수 있습니다.
따라서 다음과 같은 표현이 가능합니다:
heftychonk => heftychonk.survived
이 코드는 다음과 같은 함수와 동일합니다:
function (heftychonk) {
return heftychonk.survived;
}
3. 예시 코드 비교
직접 비교하면 이런 차이가 있습니다:
원래 작성한 코드
item.filter((v, i) => v.survived).length;
단순화한 코드
item.filter(heftychonk => heftychonk.survived).length;
이 두 코드의 기능은 동일합니다. 그러나 첫 번째 코드에서는 v와 i라는 두 개의 매개변수를 정의했지만, 실제로는 i(인덱스)를 사용하지 않습니다. 따라서 인덱스를 사용하지 않을 경우, 두 번째처럼 단순화된 코드가 더 직관적이고 가독성이 좋습니다.
4. 핵심 요약
- item.filter(heftychonk => heftychonk.survived)는 item.filter((v, i) => v.survived)와 기능적으로 동일합니다.
- 화살표 함수는 단순화된 표현으로, 매개변수가 하나일 경우 괄호를 생략할 수 있고, 단일 표현식인 경우 중괄호와 return도 생략할 수 있습니다.
- filter 함수는 콜백 함수에 (value, index, array)를 매개변수로 전달하지만, 필요한 매개변수만 사용할 수 있습니다.
따라서 단순하게 작성한 코드도 충분히 작동하며, 더 간결한 표현이 가능해진 것입니다.
나의 말:
item.filter((v, i) => v.survived).length; 여기에서는, array 파라미터가 없는 경우인가?
ChatGPT의 말:
맞아요! 질문에서 언급하신 코드:
item.filter((v, i) => v.survived).length;
여기서는 filter 함수의 세 번째 매개변수인 array 파라미터가 사용되지 않았습니다. 하지만, 그렇다고 해서 array 파라미터가 존재하지 않는 것은 아닙니다. filter 함수는 항상 (value, index, array) 세 가지 매개변수를 콜백 함수에 전달하지만, 사용하지 않을 경우 그냥 생략할 수 있습니다.
filter 콜백 함수 매개변수 정리
filter의 콜백 함수는 기본적으로 다음 세 가지 매개변수를 제공합니다:
- value (v): 현재 순회 중인 요소.
- index (i): 현재 순회 중인 요소의 인덱스.
- array: 원래의 배열(item).
따라서 filter의 콜백 함수는 아래와 같이 호출됩니다:
callback(value, index, array)
array 매개변수의 생략
array 파라미터는 필요할 때만 사용하면 되기 때문에, 일반적으로 생략됩니다. 예를 들어, 작성하신 코드에서는 array 매개변수를 사용하지 않기 때문에 단순히 (v, i)만 정의한 것입니다:
item.filter((v, i) => v.survived).length;
만약 array를 사용하려면 명시적으로 추가해야 합니다. 예를 들어, 배열 자체를 확인하려는 경우:
item.filter((v, i, array) => {
console.log(array); // 원래의 배열을 출력
return v.survived;
}).length;
array 파라미터가 없는 경우가 있나요?
array 매개변수 자체가 사라지거나 없는 상황은 없습니다. filter 함수는 항상 세 가지 매개변수를 제공합니다. 하지만 코드 작성자가 특정 매개변수를 생략하면 단순히 사용되지 않을 뿐입니다.
- 작성자 입장에서 필요하지 않은 매개변수를 정의하지 않아도 된다는 편의성 덕분에 간단한 (v, i)나 (v)만 사용하기도 하는 것이죠.
요약
- 작성한 코드에서는 array 매개변수를 정의하지 않았을 뿐, 내부적으로는 여전히 filter 함수에 의해 전달됩니다.
- 사용하지 않는 매개변수(i나 array)는 생략 가능하며, 이를 통해 코드가 간결해집니다.
- 필요한 경우 언제든 array를 추가해서 사용할 수 있습니다.
나의 말:
그러면, 축약형 표현을 쓴다해도, 파라미터 3개가 온전히 들어간 경우를 가정해서 써본다면, item.filter((v, i, item) => v.survived).length; 이렇게 되는건가?
ChatGPT의 말:
네, 정확합니다! 작성하신 코드:
item.filter((v, i, item) => v.survived).length;
이렇게 작성하면 filter 함수에 전달된 콜백 함수는 v(현재 요소), i(현재 요소의 인덱스), item(원래 배열)의 세 가지 매개변수를 받게 됩니다.
이 코드의 의미
- v: 현재 순회 중인 배열의 요소 값.
- i: 현재 요소의 인덱스.
- item: 원래 배열 (filter 메서드가 호출된 배열, 여기서는 item 자체).
예를 들어 item 배열이 아래와 같다고 하면:
const item = [
{ survived: true },
{ survived: false },
{ survived: true }
];
위 코드는 filter 내부에서 다음과 같이 실행됩니다:
item.filter((v, i, item) => {
console.log('현재 요소:', v);
console.log('현재 인덱스:', i);
console.log('원래 배열:', item);
return v.survived; // survived가 true인 경우만 필터링
});
결과적으로, survived 값이 true인 요소만 반환되고, 반환된 배열의 길이를 구합니다.
축약 표현이 더 깔끔한 이유
item.filter((v, i, item) => v.survived).length;처럼 세 매개변수를 명시하는 것은 가능한 코드지만, 필요하지 않은 매개변수를 모두 쓰면 가독성이 떨어질 수 있습니다.
- 실제로 인덱스나 원래 배열(i나 item)이 필요 없다면 다음과 같이 간단하게 작성하는 것이 더 직관적입니다:
item.filter(v => v.survived).length;
언제 모든 매개변수를 사용할까?
세 매개변수를 모두 사용하는 상황은 주로 아래와 같습니다:
1. 인덱스를 활용할 때:
- 예: 특정 인덱스 이후의 요소만 필터링하기
item.filter((v, i) => i > 1 && v.survived);
2. 원래 배열을 활용할 때:
- 예: 배열 전체를 비교하며 필터링하기
item.filter((v, i, array) => v.survived && array.length > 2);
요약
작성하신 코드:
item.filter((v, i, item) => v.survived).length;
는 완전히 유효하며, filter의 콜백 함수가 제공하는 세 가지 매개변수를 모두 사용할 수 있는 형태입니다. 하지만 필요하지 않은 매개변수를 생략하면 코드가 더 깔끔해질 수 있습니다.
Q4.
이렇게 필요 하지 않은 파라미터를 쓰지 않아도 되는 것은, JS의 경우 쓰지 않는 파라미터에 대해서는 설정되어 있는 기본값을 쓰게 할 수 있게 정해져있기 때문인가?
A4.
ChatGPT의 말:
필요하지 않은 파라미터를 쓰지 않아도 되는 이유는 JavaScript의 함수 호출 방식과 ES6의 화살표 함수(arrow function) 설계 때문입니다. 이와 관련된 내용을 단계별로 설명드릴게요.
1. JavaScript 함수의 매개변수 전달 방식
JavaScript에서 함수는 고정된 개수의 매개변수를 강제하지 않습니다. 호출 시 제공된 매개변수의 개수가 함수 정의의 매개변수 개수보다 적거나 많아도 에러가 발생하지 않습니다.
- 매개변수가 부족할 경우:
- 전달되지 않은 매개변수는 undefined로 설정됩니다.
- 매개변수가 많을 경우:
- 초과된 매개변수는 무시됩니다.
예를 들어:
function example(a, b, c) {
console.log(a, b, c);
}
example(1); // 출력: 1 undefined undefined
example(1, 2, 3, 4); // 출력: 1 2 3 (4는 무시)
이 유연한 매개변수 처리 방식 때문에 filter의 콜백 함수에서 필요하지 않은 매개변수를 선언하지 않아도 문제없이 작동합니다.
2. filter와 콜백 함수
filter 함수는 내부적으로 항상 콜백 함수에 3개의 매개변수를 전달합니다: (value, index, array).
그러나 JavaScript에서는 콜백 함수 정의 시 필요한 매개변수만 선언하면 나머지는 무시됩니다. 예를 들어:
const arr = [1, 2, 3];
// 1개만 사용
arr.filter(value => value > 1); // value만 선언
// 2개 사용
arr.filter((value, index) => index % 2 === 0); // value와 index 선언
// 3개 모두 사용
arr.filter((value, index, array) => {
console.log(array); // array 출력
return value > 1;
});
필요한 매개변수만 사용할 수 있도록 설계된 것은 사용자의 코드 간결성을 높이기 위한 JavaScript의 설계 철학 덕분입니다.
3. 화살표 함수와 간결한 표현
ES6에서 도입된 화살표 함수는 불필요한 코드 작성을 최소화하는 데 초점을 맞췄습니다.
- 파라미터가 한 개일 경우 괄호 생략 가능:
value => value > 1
- 본문이 한 줄일 경우 중괄호와 return 생략 가능:
arr.filter(value => value > 1);
따라서 filter를 사용할 때 필요한 매개변수만 명시하고, 나머지는 생략하는 것이 가독성과 효율성을 높이는 데 유리합니다.
4. 기본값 설정과는 다른 개념
질문에서 언급된 "기본값을 사용하게 정해져 있다"는 것과는 약간 다른 개념입니다. JavaScript의 기본값 매개변수(Default Parameters)는 함수 정의 시 명시적으로 값을 설정하지 않은 매개변수에 기본값을 제공하는 기능입니다. 예를 들어:
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // 출력: Hello, Guest
greet('Alice'); // 출력: Hello, Alice
filter에서 쓰지 않은 매개변수를 기본값으로 처리하지는 않습니다. 단지 JavaScript의 유연한 매개변수 전달 방식 덕분에, 사용하지 않는 매개변수를 생략할 수 있는 것뿐입니다.
요약
필요하지 않은 매개변수를 선언하지 않아도 되는 이유는:
- JavaScript 함수는 전달된 매개변수의 개수를 엄격하게 강제하지 않으며, 추가된 매개변수를 무시하거나 부족하면 undefined로 처리합니다.
- filter의 콜백 함수에서 전달된 세 개의 매개변수 (value, index, array) 중 필요 없는 것은 생략 가능하며, 이 설계는 코드 간결성을 높이기 위함입니다.
- 기본값 매개변수와는 다른 개념으로, 생략된 매개변수에 대해 기본값이 적용되지는 않습니다. 단지 무시될 뿐입니다.