6. 배열

6-1. 배열

배열(Array)은 여러 개의 값을 묶어 순차적으로 나열 및 저장하는 객체다. 데이터를 추가, 삭제, 참조, 순회 등의 다양한 작업을 수행할 때 용이하다. 배열은 대괄호([ ])를 사용하여 생성하고, 내부의 값은 요소라 하며 쉼표로 구분해 나열한다.

6-1-1. 배열의 특징

const arr =['가', '나', '다']; console.log(arr); // ['가', '나', '다'] const arr = []; // 빈 배열의 생성도 가능하다. console.log(arr); // [] (length:0) const arr = [1, 2, 3]; console.log(arr); // [1, 2, 3] const arr = new Array(4, 5, 6); console.log(arr); // [4, 5, 6] const arr = new Array(3); console.log(arr); // [empty x 3] (length:3) const arr = new Array(1); console.log(arr); // [empty] (length:1) console.log(arr[0]); // undefined (요소가 하나도 없는 배열)
 

6-1-2. 배열의 요소 순서

인덱스(index)란 요소의 순서를 의미하며, 배열의 요소에 접근할 때 사용된다. 가장 첫 번째 요소의 인덱스는 0번째로 표시한다. 다음에 오는 요소는 1번째로 표시된다.
const arr =['가', '나', '다']; console.log(arr[0]); // '가' (arr의 첫 번째 요소를 보여준다.) console.log(arr[1]); // '나' (arr의 두 번째 요소를 보여준다.) console.log(arr[2]); // '다' (arr의 세 번째 요소를 보여준다.) console.log(arr[3]); // undefined (존재하지 않는 인덱스 값은 undefined로 출력한다)
 

6-1-3. 배열의 요소 길이

배열의 길이(length) 프로퍼티를 이용하여 배열 내부에 들어있는 요소들의 개수를 확인 할 수 있다.
const arr = ['가', '나', '다']; arr.length; // 3 (배열의 길이는 3) const arr = ['lion', 'bear', 'sheep', 'monkey', 'horse']; arr.length; // 5 (배열의 길이는 5) arr[arr.length - 1]; // 'horse' (arr[5 - 1], 인덱스[4]에 해당하는 값은 horse이다.) arr[arr.length - 3]; // 'sheep' (arr[5 - 3], 인덱스[2]에 해당하는 값은 sheep이다.) arr[arr.length - 5]; // 'lion' (arr[5 - 5], 인덱스[0]에 해당하는 값은 lion이다.)
 

6-1-4. 다차원 배열

다차원 배열(Multi-Dimensional Array)은 배열 안에 다른 배열을 포함할 수 있다. 즉, 배열이 배열의 요소가 될 수 있다. 행렬을 저장하는 용도 등으로 사용된다.
const arr = [ [1, 2], [3, 4], [5, 6] ]; console.log(arr[0][0]); // 1 (인덱스 0의 배열안에서 인덱스 0의 요소는 1이다.) console.log(arr[0][1]); // 2 (인덱스 0의 배열안에서 인덱스 1의 요소는 2이다.) console.log(arr[1][1]); // 4 (인덱스 1의 배열안에서 인덱스 1의 요소는 4이다.) console.log(arr[2][1]); // 6 (인덱스 2의 배열안에서 인덱스 1의 요소는 6이다.) console.log(arr[2][2]); // undefined (존재하지 않는 인덱스 값은 undefined로 출력한다)
 
2차원 배열의 예시 살펴보기.
const arr = [ [ [1, 2], [3, 4] ], [ [5, 6], [7, 8] ] ]; console.log(arr[0][0][0]); // 1 (2차원 배열 안에서의 인덱스 0, 1차원 배열 안에서 인덱스 0, 배열 안에서 인덱스 0의 요소는 1이다) console.log(arr[0][0][1]); // 2 (2차원 배열 안에서의 인덱스 0, 1차원 배열 안에서 인덱스 0, 배열 안에서 인덱스 1의 요소는 2이다) console.log(arr[0][1][1]); // 4 (2차원 배열 안에서의 인덱스 0, 1차원 배열 안에서 인덱스 1, 배열 안에서 인덱스 1의 요소는 4이다) console.log(arr[1][0][0]); // 5 (2차원 배열 안에서의 인덱스 1, 1차원 배열 안에서 인덱스 0, 배열 안에서 인덱스 0의 요소는 5이다) console.log(arr[1][1][1]); // 8 (2차원 배열 안에서의 인덱스 1, 1차원 배열 안에서 인덱스 1, 배열 안에서 인덱스 1의 요소는 8이다) console.log(arr[2][0][1]); // Uncaught TypeError: Cannot read properties of undefined
 

6-2. 배열의 메서드

6-2-1. shift()와 unshift()

shift() 메서드는 배열의 첫 번째 요소를 꺼내고 반환한다. 또한 unshift() 메서드는 배열의 시작에 요소를 추가하고 배열의 길이를 반환한다. 아래의 예시를 통해 자세한 내용을 살펴볼 수 있다.
// 예제1 const arr = [1, 2, 3]; arr.shift(); // 1 (arr의 첫 번째 요소를 꺼내고 출력한다) console.log(arr); // [2, 3] (shift 작업으로 첫 번째 요소인 '1'을 제외하고 남은 요소들을 출력한다) // 예제2 const arr = ['연필', '노트', '충전기', '보조배터리']; arr.shift(); // '연필' (arr의 첫 번째 요소를 꺼내고 출력한다) console.log(arr); // ['노트', '충전기', '보조배터리'] (shift 작업으로 첫 번째 요소인 '연필'을 제외하고 남은 요소들을 출력한다) // 예제3 const arr = [1, 2, 3]; arr.unshift(0); // 4 (배열의 시작에 새로운 요소 '0'을 추가하여 arr 배열의 길이 4를 출력한다) console.log(arr); // [0, 1, 2, 3] (배열 시작에 추가한 요소 '0'을 포함하여 새로운 arr를 출력한다) // 예제4 const arr = ['양배추', '사과', '오이']; arr.unshift('양파'); // 4 (배열의 시작에 새로운 요소 '양파'를 추가하여 arr 배열의 길이 4를 출력한다) console.log(arr); // ['양파', '양배추', '사과', '오이'] (배열 시작에 추가한 요소 '양파'를 포함하여 새로운 arr를 출력한다)
 

6-2-2. push()와 pop()

push() 메서드는 배열의 끝에 새로운 요소를 추가하고, 배열의 길이를 출력한다. 또한 pop() 메서드는 배열의 마지막 요소를 꺼내어 반환한다. 꺼낸 요소는 더 이상 배열에 존재하지 않는다. 즉 배열에서 제외된다. 아래의 예시를 통해 자세한 내용을 살펴볼 수 있다.
// 예제1 const arr = [1, 2, 3]; arr.push(4); // 4 (배열의 끝에 새로운 요소 '4'를 추가하고, arr 배열의 길이 4를 출력한다) console.log(arr); // [1, 2, 3, 4] (배열의 끝에 추가한 요소 '4' 포함하여 새로운 arr를 출력한다) // 예제2 const arr = ['강의 듣기', '점심 먹기', '산책하기']; arr.push('저녁 먹기'); // 4 (추가 push 된 '저녁먹기' 요소를 포함하여 arr의 길이를 출력한다) arr.push('필라테스 수업 하러 가기'); // 5 (추가 push 된 '필라테스 수업 하러 가기' 요소를 포함하여 arr의 길이를 출력한다) console.log(arr); // ['강의 듣기', '점심 먹기', '산책하기', '저녁 먹기', '필라테스 수업 하러 가기'] // 예제3 const arr = [1, 2, 3]; arr.pop(); // 3 (배열의 마지막 요소 3을 꺼내어 출력한다. 요소 '3'은 더 이상 arr 배열에 존재하지 않는다) console.log(arr); // [1, 2] // 예제4 const arr = ['봄', '여름', '가을', '겨울']; arr.pop(); // '겨울' (배열의 마지막 요소 '겨울'을 꺼내어 출력한다. 요소 '겨울'은 더 이상 arr 배열에 존재하지 않는다) console.log(arr); // ['봄', '여름', '가을']
 

6-2-3. splice()

splice() 메서드는 배열의 요소를 추가, 제거 또는 교체한다. 3개의 전달 인자를 받으며 아래와 같이 각각의 위치에 인자 값을 넣으면 결괏값이 출력된다.
  • 첫 번째 인자 : 삭제나 추가를 시작할 인덱스를 입력한다.
  • 두 번째 인자 : 삭제할 요소의 개수를 입력한다.
  • 세 번째 인자 : 추가할 요소들을 입력한다. 추가할 요소가 없다면 생략이 가능하며, 1개 이상의 요소를 쉼표로 나열할 수 있다.
📌
함수 이름.splice(삭제 또는 추가를 시작할 인덱스, 삭제할 요소 개수, 추가할 요소들)
// 예제1 const nums = [1, 2, 3, 4, 5]; const newNums = nums.splice(2); // (삭제룰 시작할 인덱스 2) console.log(newNums); // [3, 4, 5]; console.log(nums); // [1, 2]; // 예제2 const arr = [1, 2, 3]; arr.splice(0,1); // [1] (삭제룰 시작할 인덱스 0, 삭제할 요소 개수 1) console.log(arr); // [2, 3] // 예제3 const arr = [2, 3, 4]; arr.splice(0, 0, 0, 1); // (삭제룰 시작할 인덱스 0, 삭제할 요소 개수 0, 추가할 요소 0, 1) console.log(arr); // [0, 1, 2, 3, 4] // 예제4 splice만 이용하여 ['다', '라', '바']를 ['가', '나', '다', '라', '마', '바']로 출력하기. const arr = ['다', '라', '바']; // 1. '바' 삭제하기. arr.splice(2, 1); // ['바'] (삭제를 시작할 인덱스 2, 삭제할 요소 개수 1) console.log(arr); // ['다', '라'] // 2. '가' 와 '나' 추가하기. arr.splice(0, 0, '가', '나'); // (추가를 시작할 인덱스 0, 삭제할 요소 개수 0, 추가할 요소 '가, 나') console.log(arr); // ['가', '나', '다', '라'] // 3. '마' 와 '바' 추가하기. arr.splice(4, 0, '마', '바'); // (추가를 시작할 인덱스 4, 삭제할 요소 개수 0, 추가할 요소 '마, 바') console.log(arr); // ['가', '나', '다', '라', '마', '바']
 

6-2-4. slice()

slice() 메서드는 배열에서 요소들을 추출하여 새로운 배열로 반환하는 메서드이다. 즉, 기존 배열에는 아무런 영향을 주지 않는다. 아래와 같이 두 개의 매개변수를 갖는다.
  • 첫 번째 인자 : 추출을 시작할 인덱스, 음수인 경우 배열의 맨 끝의 마지막 인덱스를 뜻한다.
  • 두 번째 인자 : 추출을 끝낼 인덱스로 생략이 가능하며, 이 인덱스의 요소는 추출되지 않는다. 추출할 요소는 첫 번째 인자에서 시작하여, 두 번째 인자 바로 직전 요소까지 해당한다.
// 예제1 const arr = [1, 2, 3, 4, 5]; arr.slice(0, 3); // [1, 2, 3] ('0'번째 인덱스부터 '3'번째 인덱스 바로 직전 요소까지 추출, '3'번째 인덱스는 미포함) console.log(arr); // [1, 2, 3, 4, 5] (기존 arr에는 아무런 영향을 주지 못한다) // 예제2 const arr = ['red', 'orange', 'yellow', 'green', 'blue']; arr.slice(3, 5); // ['green', 'blue'] (arr.slice(3); 일 때와 같은 값이 출력된다) console.log(arr); // ['red', 'orange', 'yellow', 'green', 'blue'] (기존 arr에는 아무런 영향을 주지 못한다) // 예제3 const arr = ['1월', '2월', '3월', '4월', '5월', '6월']; arr.slice(2); // ['3월', '4월', '5월', '6월'] ('2'번째 인덱스 '3월'부터 마지막 요소 '6월'까지 출력된다) console.log(arr); // ['1월', '2월', '3월', '4월', '5월', '6월'] // 예제4 const arr = ['대한민국', '미국', '영국', '프랑스']; arr.slice(-2); // ['영국', '프랑스'] (배열의 끝에서 요소를 '2' 개 복사하여 출력한다) console.log(arr); // ['대한민국', '미국', '영국', '프랑스']
 

6-2-5. sort()

sort() 메서드는 배열의 요소를 정렬하는 데 사용된다. 원본 배열을 직접 변경할 수 있으며, 메서드를 호출하면 배열을 변경하여 정렬된 배열을 새로 반환한다. 기본적으로는 오름차순으로 요소를 정렬한다. 아래의 예시를 통해 자세한 내용을 살펴볼 수 있다.
// 예제1 const kor = ['나', '마', '가', '라', '다']; kor.sort(); // ['가', '나', '다', '라', '마'] (배열 kor을 오름차순으로 정렬한다) console.log(kor); // ['가', '나', '다', '라', '마'] (원본 배열 kor가 새로운 배열로 정렬되어 출력된다) // 예제2 const num = [9, 3, 6, 12]; num.sort(); // [12, 3, 6, 9] console.log(num); // [12, 3, 6, 9] // 원소를 문자열로 전환하고 유니코드 포인트의 순서대로 변환하기 때문에 의도와 다른 순으로 정렬된다. // 참조 : 유니코드 (https://en.wikipedia.org/wiki/List_of_Unicode_characters) // 따라서 숫자형 데이터는 비교함수를 사용하여 정렬해야 오름차순으로 제대로 정렬된다. // 예제3 const forest = ['tree', 'bushes', 'animal']; forest.sort(); // ['animal', 'bushes', 'tree'] (배열 forest를 오름차순으로 정렬한다) console.log(forest); // ['animal', 'bushes', 'tree'] // 예제4 const forest = ['animal', 'bushes', 'tree']; forest.reverse(); // ['tree', 'bushes', 'animal'] (배열 forest를 내림차순으로 정렬한다) console.log(forest); // ['tree', 'bushes', 'animal']
 

6-2-6. forEach()

forEach() 메서드는 배열의 각 요소에 대해 주어진 함수를 실행한다. 함수는 인자로 배열 요소, 인덱스를 받는다. 배열의 요소를 순환하면서 해당 요소를 함수로 전달하여 함수가 각 요소에 대해 실행하게 된다. 아래의 예시를 통해 자세한 내용을 살펴볼 수 있다.
// 예제1 const arr = [1, 2, 3, 4, 5]; const pows = []; arr.forEach(item => pows.push(item ** 2)); // (item에 arr 배열의 요소들이 차례대로 순회 된다) console.log(pows); // [1, 4, 9, 16, 25] (12, 22, 32, 42, 5^2 값이 각각 새롭게 배열되었다) console.log(arr); // [1, 2, 3, 4, 5]; (forEach 메서드는 원본 배열을 변환하지 않는다) // 예제2 const num = [1, 2, 3, 4, 5]; num.forEach((item, index, arr) => {arr[index] = item ** 2;}); console.log(num); // [1, 4, 9, 16, 25] (forEach 메서드는 원본 배열을 변환하지 않지만 콜백함수를 통해 num 배열을 새로운 배열로 변환할 수 있다)
 

6-2-7. concat()

concat() 메서드는 인수로 추가 된 값들을 원본 배열의 마지막 요소로 추가하여 새로운 배열로 변환한다. 만약 인수로 배열이 추가되면, 배열의 요소들을 해체하여 각각의 요소로 새로운 배열에 추가된다. 그러나 추가 된 원본 배열은 변경되지 않는다. 이런 부분에서 push, unshift 메서드와 비슷하다. 차이점은 두 메서드는 원본 배열이 직접 변경되나, concat 메서드는 원본의 배열은 그대로 유지하고 새로운 배열을 반환한다는 점이다.
// 예제1 두 개의 배열 연결 const num1 = [1, 2]; const num2 = [3, 4, 5]; let result = num1.concat(num2); console.log(result); // [1, 2, 3, 4, 5] console.log(num1); // [1, 2] (기존 배열 num1, num2는 원본을 그대로 유지된다) console.log(num2); // [3, 4, 5] // 예제2 세 개의 배열 연결 const arr1 = ['가', '나']; const arr2 = ['다']; const arr3 = ['라', '마', '바']; let result = arr1.concat(arr2, arr3); console.log(result); // ['가', '나', '다', '라', '마', '바'] console.log(arr1); // ['가', '나'] console.log(arr2); // ['다'] console.log(arr3); // ['라', '마', '바'] // 예제3 단일 요소 추가하기 const num1 = [1, 2]; let result = num1.concat(3); console.log(result); // [1, 2, 3] console.log(num1); // [1, 2] // 예제4 배열을 추가하기 const num1 = [1, 2]; let result = num1.concat(3, [4, 5, 6]); console.log(result); // [1, 2, 3, 4, 5, 6] (인수로 전달된 값이 배열인 경우, 배열을 해체하여 새로운 배열의 요소로 추가한다) console.log(num1); // [1, 2]
// 예제1 두 개의 배열 연결 const num1 = [1, 2]; const num2 = [3, 4, 5]; let result = num1.concat(num2); console.log(result); // [1, 2, 3, 4, 5] console.log(num1); // [1, 2] (기존 배열 num1, num2는 원본을 그대로 유지된다) console.log(num2); // [3, 4, 5] // 예제2 세 개의 배열 연결 const arr1 = ['가', '나']; const arr2 = ['다']; const arr3 = ['라', '마', '바']; let result = arr1.concat(arr2, arr3); console.log(result); // ['가', '나', '다', '라', '마', '바'] console.log(arr1); // ['가', '나'] console.log(arr2); // ['다'] console.log(arr3); // ['라', '마', '바'] // 예제3 단일 요소 추가하기 const num1 = [1, 2]; let result = num1.concat(3); console.log(result); // [1, 2, 3] console.log(num1); // [1, 2] // 예제4 배열을 추가하기 const num1 = [1, 2]; let result = num1.concat(3, [4, 5, 6]); console.log(result); // [1, 2, 3, 4, 5, 6] (인수로 전달된 값이 배열인 경우, 배열을 해체하여 새로운 배열의 요소로 추가한다) console.log(num1); // [1, 2]
// 배열 2개를 concat()으로 합쳐서 새로운 배열 만들기 var nums = [1, 2, 3, 4, 5]; var kors = ['가', '나', '다', '라', '마']; var numsKors = nums.concat(kors); console.log(numsKors); // [1, 2, 3, 4, 5, '가', '나', '다', '라', '마'] var korsNums = kors.concat(nums); console.log(korsNums); // ['가', '나', '다', '라', '마', 1, 2, 3, 4, 5]
 

6-2-8. join()

join() 메서드는 배열의 요소들을 연결하여 하나의 문자열로 만들어 준다. 요소 사이에 구분자는 보통 쉼표를 사용하며 슬래시를 사용할 수도 있다. 아래의 예시를 통해 자세한 내용을 살펴볼 수 있다.
var nums = [1, 2, 3, 4, 5]; var kors = ['가', '나', '다', '라', '마']; var string_1 = nums.join(); console.log('구분자 지정을 별도로 안 하면: ', string_1); // 구분자 지정을 별도로 안 하면: 1,2,3,4,5 var string_2 = kors.join(); console.log('"/"로 구분자를 지정하면: ', string_2); // "/"로 구분자를 지정하면: 가,나,다,라,마