Index
1. 배열
1.1 요소, 값으로 인정하는 모든 것은 배열의 요소
1.1.1 원시값
const arr = [1, "hello", true, null, undefined];
console.log(arr); // [1, "hello", true, null, undefined]
1.1.2 객체와 배열
const arr = [
{ key: "value" }, // 객체
[1, 2, 3], // 배열
"hello",
];
console.log(arr[0].key); // "value"
console.log(arr[1][2]); // 3
1.1.3 함수
const arr = [
function () {
return "I am a function";
},
() => "I am an arrow function",
];
console.log(arr[0]()); // "I am a function"
console.log(arr[1]()); // "I am an arrow function"
1.1.4 혼합형
const arr = [
42,
"JavaScript",
{ language: "JS" },
[1, 2, 3],
function () {
return "Dynamic!";
},
];
console.log(arr[2].language); // "JS"
console.log(arr[3][1]); // 2
console.log(arr[4]()); // "Dynamic!"
<hr style="border: 1px dashed #ccc;" />
1.2 다른 언어와 비교
1.2.1 동적타입 지원
- Javascript 배열은 동적타입(Dynamic Typing)을 지원하기 때문에 배열 요소가 서로 다른 데이터 타입을 가질 수 있다.
- 반면, Java나 C++ 같은 언어는 배열이 특정 타입만 저장하도록 제안된다.
int[] arr = {1, 2, 3}; // 정수형만 가능
arr[1] = "hello"; // 컴파일 에러!
1.2.2 가변 길이
- Javascript 배열은 길이가 고정되지 않는다. 필요에 따라 동적으로 크기를 늘리거나 줄일 수 있다.
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
1.2.3 다차원 배열에 제한 없음
- Javascript는 배열 안에 배열(다차원 배열)을 자유롭게 중첩시킬 수 있다.
- Java 같은 언어는 다차원 배열을 지원하지만 배열의 타입은 고정된다.
1.2.4 함수를 배열에 저장 가능
- Javascript에서 함수가 1급 객체(First-Class-Object)로 취급되므로 배열 요소로 사용 가능하다.
- 대부분의 정적 언어에서는 함수가 배열의 요소가 될 수 없다.
1.3 실제 활용 사례
1.3.1 데이터 구조 표현
다양한 형태의 데이터를 하나의 배열로 관리할 수 있다.
const user = ["John", 30, { role: "admin" }, [1, 2, 3]];
1.3.2 함수와 객체 결합
이벤트 핸들링, 콜백 함수 관리 등에 유용하게 사용할 수 있다.
const tasks = [() => console.log("Task 1"), () => console.log("Task 2")];
tasks.forEach((task) => task());
1.4 단점 또는 주의점
배열에 다양한 타입의 데이터를 저장할 수 있는 유연성은 편리하지만, 다음과 같은 단점도 있다.
- 코드의 예측 가능성 저하: 여러 타입이 섞이면 배열 요소를 다룰 때 혼란스러울 수 있다.
- 퍼포먼스 저하: 정적 타입 언어보다 실행 속도가 느릴 수 있다.
🧐 Q. 객체와 배열은 무슨 차이가 있을까?
Answer) 일반 객체와 배열을 구분하는 가장 명확한 차이는 “값의 순서”와 “length 프로퍼티”다. 인덱스로 표현되는 값의 순서와 length
프로퍼티를 갖는 배열은 반복문을 통해 순차적으로 값에 접근하기 적합한 자료구조다.

Difference of Object and Array
Jay Tak
🧐 Q. 인덱스로 배열 요소를 읽거나 쓰는 작업은 일반적인 배열보다 느릴수 있다는 의미는 무엇일까?
Answer)
-
C, C++, Java 등에서는 배열이 정적 구조로 동작
- 배열의 크기와 각 요소의 데이터 타입이 고정되어 있습니다.
- 예를 들어,
int[5]
배열은 5개의 정수형(int) 데이터를 연속된 메모리 공간에 저장합니다.
-
JavaScript 배열은 동적 배열로 동작
- 배열의 크기가 고정되지 않고, 데이터를 추가하거나 제거할 수 있습니다.
- 배열의 각 요소는 서로 다른 데이터 타입을 가질 수 있습니다.
-
C, C++, Java 등 인덱스 접근
- 예: 배열의 첫 번째 요소의 메모리 주소가
1000
이라고 가정하면,arr[3]
의 주소는 단순히1000 + (3 * 데이터 크기)
로 계산됩니다. - 즉, 배열의 메모리 주소를 산술적으로 계산하기 때문에 접근 속도가 빠릅니다.
arr[3]
→ 메모리 주소 계산(산술 연산) → 데이터 접근(매우 빠름).
- 예: 배열의 첫 번째 요소의 메모리 주소가
-
javascript)에서 인덱스 접근
-
JavaScript 배열은 내부적으로 객체처럼 구현됩니다. 배열의 요소는 실제로 키-값 쌍으로 저장됩니다.
-
JavaScript 배열은 키를 기반으로 값을 검색하기 때문에, 일반적인 배열의 메모리 주소 계산 방식과는 다릅니다.
-
arr[3]
→ 키를 기반으로 값 검색 → 메모리에서 데이터를 가져옴(약간 느릴 수 있음).const arr = [10, 20, 30]; // 내부적으로는 객체처럼 동작 // arr = { "0": 10, "1": 20, "2": 30 }
-
🧐 Q. 유사배열 객체와 이터러블 객체의 차이는 무엇일까?
Answer)
A1. 유사배열 객체(Array-like Object)
유사배열 객체는 배열처럼 동작할 수 있는 객체로, 배열과 유사한 구조를 가지고 있지만 배열(Array)은 아닙니다.
A1.1 인덱스와 length
속성을 가짐
- 객체 내부에 숫자형 키(인덱스)와
length
속성을 가지고 있습니다.
const arrayLike = {
0: "Hello",
1: "World",
length: 2,
};
console.log(arrayLike[0]); // "Hello"
console.log(arrayLike.length); // 2
A1.2 배열 메서드를 직접 사용할 수 없음
const arrayLike = {
0: "Hello",
1: "World",
length: 2,
};
// 배열 메서드 사용하려면 Array.prototype 빌리기
const result = Array.prototype.map.call(arrayLike, (item) => item + "!");
console.log(result); // ["Hello!", "World!"]
A1.3 이터러블이 아님
const arrayLike = {
0: "Hello",
1: "World",
length: 2,
};
// 이터러블이 아니기 때문에 에러 발생
for (const item of arrayLike) {
console.log(item); // TypeError: arrayLike is not iterable
}
A2. 이터러블(Iterable)
이터러블(Iterable)은 Symbol.iterator
메서드를 구현한 객체로, 반복 가능한(iterable) 구조를 가집니다.
A2.1 Symbol.iterator
메서드가 있음
이터러블 객체는 Symbol.iterator
라는 특별한 메서드를 가지고 있습니다. 이 메서드는 이터레이터(iterator)를 반환합니다. 이터레이터는 next()
메서드를 통해 값을 하나씩 반환하며, done
이 true
일 때 반복이 종료됩니다.
const iterable = {
[Symbol.iterator]: function () {
let step = 0;
return {
next: function () {
step++;
if (step === 1) return { value: "Hello", done: false };
if (step === 2) return { value: "World", done: false };
return { value: undefined, done: true };
},
};
},
};
for (const value of iterable) {
console.log(value); // "Hello", "World"
}
A2.2 for...of
및 spread
문법 사용 가능
const iterable = ["Hello", "World"]; // 배열은 기본적으로 이터러블
for (const value of iterable) {
console.log(value); // "Hello", "World"
}
const copy = [...iterable];
console.log(copy); // ["Hello", "World"]
A2.3 배열도 이터러블
const arr = [1, 2, 3];
console.log(typeof arr[Symbol.iterator]); // "function"
A2.4 유연한 데이터 구조 반복 가능
const str = "Hello";
for (const char of str) {
console.log(char); // "H", "e", "l", "l", "o"
}

Difference of Array-like Object and Iterable
Jay Tak
2. 배열 고차함수
2.1 Array.prototype.sort
sort
메서드는 기본적으로 배열의 요소를 문자열로 변환한 뒤 유니코드 코드 포인트 순서에 따라 정렬합니다.
숫자 배열도 기본적으로 문자열로 변환되어 유니코드 순서대로 정렬되므로, 숫자 크기와 무관한 결과가 나옵니다.
[2, 10].sort(); // [10, 2] (문자열 "10"이 "2"보다 앞)
2.1.1 비교함수를 사용한 해결
숫자를 크기 순서대로 정렬하려면 비교 함수(comparator function)를 sort
메서드에 전달해야 합니다.
-
음수(
a - b < 0
): 첫 번째 값이 두 번째 값보다 앞. -
0(
a - b === 0
): 순서 유지. -
양수(
a - b > 0
): 두 번째 값이 첫 번째 값보다 앞.
[2, 10].sort((a, b) => a - b); // [2, 10]
<hr style="border: 1px dashed #ccc;" />
2.2 Arrary.prototype.forEach
-
forEach 메서드의 콜백 함수는 forEach 메서드를 호출한 배열의 요소값과 인덱스, forEach 메서드를 호출한 배열 자체, 즉 this 1를 순차적으로 전달받을 수 있다.
-
콜백 함수를 통해 원본배열 변경 가능
class Numbers 1
numberArray = [];
multiply(arr) {
arr.forEach(function (item) {
this.numberArray.push(item * item);
}, this); 1 // forEach 메서드의 콜백 함수 내부에서 this로 사용할 객체를 전달
}
}
const numbers = new Numbers();
numbers.multiply([1, 2, 3]);
console.log(numbers.numberArray); // [1, 4, 9]
2.3 Array.prototype.map
-
map 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다. 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.
-
이때 원본 배열은 변경되지 않는다.
class Prefixer {
constructor(prefix) {
this.prefix = prefix;
}
add(arr) {
// 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.
return arr.map((item) => this.prefix + item);
}
}
const prefixer = new Prefixer("-webkit-");
console.log(prefixer.add(["transition", "user-select"]));
// ['-webkit-transition', '-webkit-user-select']
2.4 Array.prototype.filter
-
filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한 다. 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다.
-
이때 원본 배열은 변경되 지 않는다.
class Users {
constructor() {
this.users = [
{ id: 1, name: "Lee" },
{ id: 2, name: "Kim" },
];
}
// 요소 추출
findById(id) {
// id가 일치하는 사용자만 반환한다.
return this.users.filter((user) => user.id === id);
}
// 요소 제거
remove(id) {
// id가 일치하지 않는 사용자들만 남긴다.
this.users = this.users.filter((user) => user.id !== id);
}
}
const users = new Users();
let user = users.findById(1);
console.log(user); // [{ id: 1, name: 'Lee' }]
// id가 1인 사용자를 제거한다.
users.remove(1);
user = users.findById(1);
console.log(user); // []
2.5 Array.prototype.reduce
reduce
는 배열의 각 요소를 순회하며, 콜백 함수의 반환값을 누적(accumulate)합니다.- 반환값은 다음 순회의 첫 번째 인수(누적값)로 전달되며, 마지막 순회가 끝난 후 최종 누적값을 반환합니다.
- 원본 배열은 변경되지 않습니다(비파괴적 메서드).
2.5.1 reduce
메서드의 인수
2.5.1.1 콜백함수
- 형식:
(accumulator, currentValue, index, array)
accumulator
: 이전 순회에서 반환된 값(누적값).currentValue
: 현재 처리 중인 배열의 요소.index
: 현재 요소의 인덱스.-
array
: 현재 배열(전체 배열).2.5.1.2 초기값
accumulator
의 초기값을 설정합니다. 생략하면 배열의 첫 번째 요소가 초기값으로 사용됩니다.
2.5.2 평균 구하기
const values = [1, 2, 3, 4, 5, 6];
const average = values.reduce((acc, cur, i, { length }) => {
// 마지막 순회가 아닌 경우 누적값을 계산
// 마지막 순회라면 누적값을 길이로 나눠 평균을 반환
return i === length - 1 ? (acc + cur) / length : acc + cur;
}, 0);
console.log(average); // 3.5
2.5.3 최대값 구하기
const values = [1, 2, 3, 4, 5];
const max = values.reduce((acc, cur) => (acc > cur ? acc : cur), 0);
console.log(max); // 5
2.5.4 요소의 중복 횟수 구하기
const fruits = ["banana", "apple", "orange", "orange", "apple"];
const count = fruits.reduce((acc, cur) => {
// 현재 요소를 키로 사용하고, 등장 횟수를 값으로 저장
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
console.log(count);
// { banana: 1, apple: 2, orange: 2 }
<hr style="border: 1px dashed #ccc;" />
2.6 Array.prototype.some
- 배열의 요소 중 하나라도 조건을 만족하면
true
를 반환하고, 모두 만족하지 않으면false
를 반환합니다. - 조건이
true
인 요소를 찾으면 즉시 순회를 멈춥니다. - 조건을 확인하는 콜백 함수는 배열의 요소, 인덱스, 배열 자체를 순서대로 전달받습니다.
- 배열이 비어 있으면 언제나
false
를 반환합니다.
[5, 10, 15].some((item) => item < 0); // false
<hr style="border: 1px dashed #ccc;" />
2.7 Array.prototype.every
- 배열의 모든 요소가 조건을 만족하는지 확인합니다.
- 모든 요소가 조건을 만족하면
true
. - 하나라도 조건을 만족하지 않으면
false
.
[5, 10, 15].every((item) => item > 10); // false
<hr style="border: 1px dashed #ccc;" />
2.8 Array.prototype.find
- 배열의 요소 중 조건을 만족하는 첫 번째 요소를 반환합니다.
- 조건을 만족하는 요소를 찾으면 즉시 순회를 멈추고 그 요소를 반환합니다.
- 조건을 만족하는 요소가 없으면
undefined
를 반환합니다.
const users = [
{ id: 1, name: "Lee" },
{ id: 2, name: "Kim" },
{ id: 2, name: "Choi" },
{ id: 3, name: "Park" },
];
const user = users.find((user) => user.id === 2);
console.log(user); // { id: 2, name: 'Kim' }
<hr style="border: 1px dashed #ccc;" />
2.9 Array.prototype.findIndex
- 배열의 요소 중 조건을 만족하는 첫 번째 요소의 인덱스를 반환합니다.
- 조건을 만족하는 요소가 있으면 그 인덱스를 반환.
- 조건을 만족하는 요소가 없으면
-1
을 반환합니다.
const users = [
{ id: 1, name: "Lee" },
{ id: 2, name: "Kim" },
{ id: 2, name: "Choi" },
{ id: 3, name: "Park" },
];
const index = users.findIndex((user) => user.id === 2);
console.log(index); // 1
<hr style="border: 1px dashed #ccc;" />
2.10 Array.prototype.flatMap
map
메서드로 배열을 변환한 후, 결과를 1단계 평탄화(Flatten)합니다.map
+flat(1)
을 결합한 것과 동일하게 동작합니다.- 배열의 중첩 구조를 한 단계만 평탄화할 수 있습니다.
- 평탄화 깊이를 지정할 수는 없습니다(항상 1단계).
const arr = ["hello", "world"];
const result = arr.map((x) => x.split("")).flat();
console.log(result); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
const result = arr.flatMap((x) => x.split(""));
console.log(result); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
// 항상 1단계만 평탄화
const arr = ["hello", "world"];
const result = arr.flatMap((str, index) => [index, str, str.length]);
console.log(result); // [0, 'hello', 5, 1, 'world', 5]
// 추가 평탄화시 flat을 보조로 사용
const result = arr.map((str, index) => [index, str, str.length]).flat(2);
console.log(result); // [0, 'hello', 5, 1, 'world', 5]