배열(Array)은
연관된 data를 메모리상에 연속적이며 순차적으로 미리 할당된 크기만큼 저장하는 자료구조 입니다.
배열 생성 방법
# 1. 생성자 함수
let array = new Array(2);
console.log(array); // [<2 empty items>]
let array2 = new Array(1, 2, 3, 4);
console.log(array2); // [1,2,3,40]
# 2. Array.of
let array3 = Array.of(1,2);
console.log(array3); // [1,2]
# 3. 배열 리터럴
let array4 = [1,2,3];
console.log(array4); // [1,2,3]
# 4. Array.from : 기존의 배열로부터 새로운 배열을 만듦
let array5 = Array.from(array4)
console.log(array5) ; // [1,2,3]
// 또한 순회가 가능(이터러블)
array5 = Array.from('hello');
console.log(array5); // ['h','e','l','l','o']
자바스크립트에서 배열의 특징
일반적으로 배열은 동일한 메모리 크기를 가지며 연속적으로 이어져 있습니다.
하지만 자바스크립트에서의 배열은 연속적으로 이어져 있지 않고 객체와 유사 합니다.
자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체 입니다.
자바스크립트에서 배열은 요소를 위한 각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며
연속적으로 이어져 있지 않을 수도 있습니다. 이러한 배열을 희소 배열(sparse array)
라고 합니다.
- 이러한 특징을 보완하기 위해 타입이 정해져 있는 배열이 있습니다.
let array = Array.from({
0: 'hello',
1: 'world'
length: 2,
});
console.log(array); // ['hello','world']
자바스크립트의 배열이 다른 언어와 다른 이유
GPT 친구에게 도움을 요청해봤습니다.
객체로 구현되는 JavaScript 배열의 역사는 언어 개발 초기로 거슬러 올라갑니다. Brendan Eich는 1990년대 중반에 Netscape Communications Corporation에서 JavaScript(원래 LiveScript라고 알려짐)를 만들었을 때 이를 웹용 경량 스크립팅 언어로 만드는 것을 목표로 삼았습니다.
데이터 컬렉션으로 작업하는 편리한 방법을 제공하기 위해 JavaScript는 내장 데이터 유형으로 배열을 도입했습니다. 그러나 당시의 디자인 결정과 언어 제약으로 인해 배열을 객체로 구현하는 것이 실용적인 선택이었습니다.
JavaScript는 배열을 객체로 나타내는 Self 언어의 영향을 많이 받았습니다. 이 접근 방식은 JavaScript의 전반적인 객체 지향 특성과 일치하며 배열이 Object 프로토타입에서 속성과 메서드를 상속하도록 허용했습니다.
또한 JavaScript의 동적이고 느슨한 유형 특성으로 인해 다양한 데이터 유형을 수용할 수 있는 유연한 배열을 갖는 것이 바람직했습니다. 배열을 객체로 구현함으로써 JavaScript 배열은 이기종 요소를 보유하고 언어의 동적 특성에 맞는 동적 크기 조정을 허용할 수 있습니다.
JavaScript가 인기를 얻고 ECMAScript 사양을 통해 표준화됨에 따라 배열을 객체로 나타내려는 결정이 언어의 근본적인 측면이 되었습니다. 이 선택은 기존 코드베이스와의 이전 버전과의 호환성을 보장하고 주요 변경 사항을 방지하기 위해 유지되었습니다.
시간이 지남에 따라 JavaScript 배열은 객체와 같은 동작을 유지하면서 기능을 향상시키기 위해 특정 배열 관련 메서드 및 속성을 포함하도록 발전했습니다. 배열 관련 기능과 객체 상속의 이러한 조합으로 인해 JavaScript 배열은 언어에서 독특하고 강력한 데이터 구조가 되었습니다.
다른 프로그래밍 언어는 배열에 대해 다른 구현을 가질 수 있지만 JavaScript 배열을 객체로 표현하기로 한 결정은 언어 디자인 및 구문의 정의 특성이 되었습니다.
다른 배열과는 다른 자바스크립트의 배열 예시
# length 프로퍼티는 배열의 길이를 나타내는 0 이상의 정수를 값으로 갖는다.
const arr = [1, 2, 3];
console.log(arr.length); // 3
arr.push(4);
console.log(arr.length); // 4
arr.pop();
console.log(arr.length); // 3
-----
const arr = [1, 2, 3, 4, 5];
arr.length = 3;
console.log(arr); // [1, 2, 3]
-----
# length 프로퍼티에 임의의 값을 할당할 수도 있다.
const arr = [1, 2];
arr.length = 4;
console.log(arr.length); // 4
console.log(arr); // [ 1, 2, <2 empty items> ]
# empty items는 실제로 추가가 되지는 않는다.
# 현재 length 프로퍼티 값보다 큰 숫자를 할당하게 되면 length는 변경되지만 실제 배열에는 아무 변화가 없다.
-----
# 값이 없는 요소를 위해 메모리 공간을 확보하지 않은 것을 확인할 수 있다.
console.log(Object.getOwnPropertyDescriptors(arr));
/*
{
'0': { value: 1, writable: true, enumerable: true, configurable: true },
'1': { value: 2, writable: true, enumerable: true, configurable: true },
length: { value: 4, writable: true, enumerable: false, configurable: false }
}
*/
배열을 참조하는 방법
const numbers = [1, 2, 3, 4];
console.log(numbers[0]); // 1
console.log(numbers[1]); // 2
배열을 다룰 때 추가, 삭제 방법 안좋은 예시 ❌
const numbers = [1, 2, 3, 4];
numbers[4] = 5;
console.log(numbers); // [1,2,3,4,5]
# 직접 인덱스를 조작하면 실수로 인해 빈 공간이 생길 수 있습니다.
numbers[7] = 6;
console.log(numbers); // [1,2,3,4,5,,,6]
# delete를 사용해서 삭제하는 경우 삭제하고 남아있게 됩니다.
delete numbers[1]
console.log(numbers); // [1,,3,4,5,,,6]
유용한 배열의 메서드
- 특정한 요소가 배열인지 체크
배열이라면 true, 배열이 아니면 false
const numbers = [1, 2, 3, 4];
console.log(Array.isArray(numbers)); // true
console.log(Array.isArray({})); // false
- 특정한 요소의 위치를 찾는 경우
const numbers = [1, 2, 3, 4];
console.log(numbers.indexOf(3)); // 2
- 배열안에 특정한 요소가 있는지 체크
요소가 있으면 true, 없으면 false
const numbers = [1, 2, 3, 4];
console.log(numbers.includes(3)); // true
- 배열 요소 추가
제일 뒤에 추가하는 경우 push
→ 배열 자체를 수정
const numbers = [1, 2, 3, 4];
numbers.push(5);
console.log(numbers); // [1,2,3,4,5];
제일 앞에 추가하는 경우 unshift
→ 배열 자체를 수정
const numbers = [1, 2, 3, 4];
numbers.unshift(5);
console.log(numbers); // [5,1,2,3,4];
- 배열 요소 제거
제일 뒤 제거하는 경우 pop
→ 배열 자체를 수정 그리고 반환된 요소를 리턴 합니다.
const numbers = [1, 2, 3, 4];
const lastItem = numbers.pop();
console.log(numbers); // [1,2,3];
console.log(lastItem); // 4
제일 앞 요소를 제거 경우 shift
→ 배열 자체를 수정 그리고 반환된 요소를 리턴 합니다.
const numbers = [1, 2, 3, 4];
const lastItem = numbers.shift();
console.log(numbers); // [2,3,4];
console.log(lastItem); // 1
- 배열 중간에 추가, 삭제 방법
splice
는 배열 자체를 수정합니다.
그리고 삭제된 요소를 배열 형태로 리턴 합니다.
const numbers = [1, 2, 3, 4];
const returnValue = numbers.splice(1, 1); // 인덱스 1부터 1개를 삭제한다.
console.log(numbers); // [1,3,4]
console.log(returnValue); // [2]
splice
는 삭제하고 추가 할 수 있습니다.
const numbers = [1, 2, 3, 4];
numbers.splice(1, 0, 5, 6); // 인덱스 1 자리에 0(아무것도 삭제하지 않고) 5,6 을 추가한다.
console.log(numbers); // [1,5,6,2,3,4]
numbers.splice(1, 1, 10); // 인덱스 1자리부터 1개를 지우고 10을 추가한다.
console.log(numbers); // [1,10,6,2,3,4]
- 배열을 잘라서 새로운 배열로 만드는 경우
slice
를 사용 합니다.
첫번째 인자로 시작 인덱스(index) 두번째 인자로 종료 인덱스
시작 인덱스부터 종료 인덱스까지 값을 복사하여 반환합니다.
시작 인덱스, 종료 인덱스 모두 선택적 입니다.
const numbers = [1, 2, 3, 4];
const newArr = numbers.slice(0, 2);
console.log(numbers); // [1,2,3,4]
console.log(newArr); // [1,2]
const arr2 = numbers.slice();
console.log(arr2); // [1,2,3,4]
const arr3 = numbers.slice(1);
console.log(arr3); // [2,3,4]
const arr4 = numbers.slice(-1);
console.log(arr4); // [4]
- 배열 붙이기
concat
을 사용하면 기존의 배열은 유지하고 배열을 이어붙여 새로운 배열을 리턴해줍니다.
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = arr1.concat(arr2);
console.log(arr1); // [1,2]
console.log(arr2); // [3,4]
console.log(arr3); // [1,2,3,4]
- 배열 순서 거꾸로
reverse
를 사용하면 기존의 배열도 바꾸면서 거꾸로 뒤집어 새로운 배열을 리턴해줍니다.
const numbers = [1, 2, 3, 4];
const arr = numbers.reverse();
conosle.log(numbers); // [4,3,2,1]
console.log(arr); // [4,3,2,1]
- 중첩 배열을 하나로 만들기
flat
을 사용 합니다.
flat() 은 기본적으로 1단계
(n) 을 하면 더 많은 중첩된 배열을 풀어줍니다.
기존 배열은 유지
const arr = [1, 2, 3, [4, 5, [6, 7]]];
const arr2 = arr.flat();
console.log(arr); // [1, 2, 3, [4, 5 ,[6,7]]];
console.log(arr2); // [1,2,3,4,5,[6,7]]
const arr3 = arr.flat(2);
console.log(arr3); // [1,2,3,4,5,6,7]
- 특정한 값으로 배열 채우기
fill
을 사용 합니다.
fill 은 어떠한 값으로 채울 것인지 또한 어디서 어디까지를 정할 수 있습니다.(옵션)
배열 자체를 수정 합니다.
const numbers = [1, 2, 3, 4];
numbers.fill(2);
console.log(numbers); // [2,2,2,2]
numbers.fill("a", 1, 3);
console.log(numbers); // [2,"a","a",2]
numbers.fill("a", 1);
console.log(numbers); // [2,"a","a","a"]
- 배열을 문자열로 합치는 경우
join
을 사용 합니다.
기존 배열을 유지 합니다.
join(문자) 문자를 사용해서 나누고 싶은 기호를 적을 수 있습니다.
const numbers = [1, 2, 3, 4];
const arr = numbers.join();
const arr2 = numbers.join(|);
console.log(numbers); // [1,2,3,4]
console.log(arr); // "1,2,3,4"
console.log(arr2); // "1|2|3|4"