배열의 형태
let arr = [1, 2, 3, 4];
console.log(arr); // [1, 2, 3, 4]
배열 생성 방법
배열 생성자를 이용해 배열을 생성하는 방법
let arr1 = new Array(3); // 배열의 사이즈를 정하는 경우
console.log(arr1); //[ <3 empty items> ]
let arr2 = new Array(1, 2, 3); // 배열의 실제 item을 정의하는 경우
console.log(arr2); // [ 1, 2, 3 ]
생성자가 아닌 Array의 static 함수를 이용하여 만들수도 있다.
let arr3 = Array.of(1, 2, 3);
console.log(arr3) // [1, 2, 3]
그리고 배열생성자 Array.from() 함수가 있다.
ES6에서 업데이트가 되었는데,
Array.from() 함수를 풀어보면 ArrayLike와 Iterable 을 매개변수로 전달하면 배열을 생성하는 기능을 한다고 되어있다.
대표적으로 배열, 유사배열, 문자열에 이 함수를 사용하는데
- 배열을 실행하면, 그 item들을 복사하여 새로운 배열을 생성하고,
- 유사배열 객체를 실행하면, item들을 복사하여 실제배열을 생성한다.
- 문자열을 전달하면 각 문자를 요소로 갖는 배열을 생성한다.
let array1 = [1, 2, 3, 4];
let array2 = '1234';
arr1 = Array.from(array1);
arr2 = Array.from(array2);
console.log(arr1); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]
ArrayLike(유사배열)?
유사 배열 객체는 숫자 인덱스를 사용하여 요소에 접근할 수 있고, length 속성을 가지고 있지만, 배열 메서드(예: push, pop, map, forEach 등)를 사용할 수 없다.
예를 들어, arguments 객체나 DOM의 NodeList와 같은 객체가 유사 배열이다.
이들은 배열처럼 동작하지만, 배열의 메서드는 사용할 수 없다.
arr3 = Array.from({
0: '1',
1: '2',
2: '3',
3: '4',
length: 4,
});
console.log(arr3); //[ '1', '2', '3', '4' ]
전통적인 프로그래밍 언어에서는 배열이 동일한 메모리 크기를 가지며 연속적으로 배치되는 경우가 많다.
그러나 JS에서의 배열은 배열의 모습과 특징을 가지고 있지만, 실제로는 객체로서 동작한다. 반전
const arr1 = new Array(1, 2, 3); // Array의 인스턴스 생성
console.log(arr1 instanceof Array); // true
const arr2 = [1, 2, 3]; // 심지어 배열 리터럴로 선언해도?
console.log(arr2 instanceof Array); // true
처음에 생성자를 이용해 생성했던 배열을 생각해보면 Array의 인스턴스였던것.
배열 리터럴을 할당하여 배열을 생성한 경우에도 내부적으로 Array 생성자가 호출되어 배열의 인스턴스가 만들어지는 것이다.
아무튼 이 JS에서의 배열은 다양한 데이터 타입을 수용할 수 있도록 설계되어 있어,
숫자, 문자열, 객체 등 여러 유형의 데이터를 포함할 수 있다.
이러한 유연성 덕분에 데이터 처리에 있어 편리하지만, 성능 측면에서는 비효율적일 수 있다.
이는 배열의 요소가 다양한 타입일 경우, JS엔진이 이를 처리하는 데 추가적인 오버헤드가 발생할 수 있기 때문이다.
이걸 보완하기 위해서 JS에는 타입이 정해져 있는 타입 배열이 있다.
배열 item 참조
인덱스를 사용한 참조.
0부터 시작하는 인덱스를 사용하여 특정 요소에 접근할 수 있다.
const arr = ['a', 'b', 'c', 'd'];
console.log(arr[0]); // 'a'
console.log(arr[2]); // 'c'
for문 사용
for 루프를 사용하여 배열의 모든 요소를 순회하고 참조할 수 있다.
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 'a', 'b', 'c', 'd' 순차적으로 출력
}
for...of문 사용
item을 나타내는 상수로 좀 더 간단하게 표현할 수 있다.
for (const item of arr) {
console.log(item); // 'a', 'b', 'c', 'd' 순차적으로 출력
}
forEach 메서드 사용
Array.prototype.forEach 메서드를 사용하여 배열의 각 요소에 대해 함수를 실행할 수 있다.
arr.forEach((item) => {
console.log(item); // 'a', 'b', 'c', 'd' 순차적으로 출력
});
item 추가 삭제
일반적으로 배열의 아이템도 객체 속성과 같이, 직접접근하여 추가, 삭제가 가능하다.
여러 메서드들이 있지만 우선 직접 추가 삭제에 대해서 한번 알아보자
const arr = ['a', 'b', 'c', 'd'];
arr[4] = 'e'
delete arr[0];
console.log(arr); // [ <1 empty item>, 'b', 'c', 'd', 'e' ]
배열arr 5번째 index에 item을 추가하였다.
이처럼 item 비어있는 index에 직접 추가할 수도 있으며, 이미 item이 있으면 item이 덮어쓰기 된다.
그리고 첫번째 item을 삭제하었다.
직접 삭제하게 되면 위에 결과처럼 <1 empty item> 으로 해당 index가 비어있게 된다는 것을 알 수 있다.
이렇게 직접접근하여 추가 삭제 하는 방법은 나중에 배열을 지저분하게 만들거나, 오류를 야기할 수 있기에 잘 쓰이지 않는다.
배열관련메서드
추가삭제뿐 아니라 배열을 사용함에 있어 자주 사용하게될 여러 함수들을 차례로 알아보자
메서드를 처음 배울때는 매개변수인 배열 자체를 변경하는지, 새로운 배열을 복제하여 반환하는지 잘 파악하는게 좋다.
Array.isArray();
배열인지 체크하는 메서드
const arr = ['a', 'b', 'c', 'd'];
console.log(Array.isArray(arr)); // true
indexOf();
item의 index 번호를 반환
const arr = ['a', 'b', 'c', 'd'];
console.log(arr.indexOf('b')); // 1
includes();
배열의 특정 값이 item으로 속해있는지 체크
const arr = ['a', 'b', 'c', 'd'];
console.log(arr.includes('b')); // true
push();
배열 끝에 item을 추가.
const arr = ['a', 'b', 'c', 'd'];
arr.push('e', 'f'); // 여러개를 전달해도됨
console.log(arr); // [ 'a', 'b', 'c', 'd', 'e', 'f' ]
let length = arr.push('g');
console.log(length); // 7
또한 변경된 뒤의 배열 item 갯수를 반환
unshift();
배열 앞에 추가함.
pop();
제일 뒤에 있는 item을 삭제. 삭제된 item을 반환. 배열 자체를 업데이트함.
const arr = ['a', 'b', 'c', 'd'];
let last = arr.pop();
console.log(arr); // [ 'a', 'b', 'c' ]
console.log(last); // d
shift(); // 배열 앞의 item을 삭제
fill();
지정한 범위까지의 index를 특정 값으로 덮어씀.
const arr = [1, 2, 3, 4, 5, 6];
console.log(arr.fill(0)) // [0, 0, 0, 0, 0, 0]
console.log(arr.fill('0', 1, 3)) // [1, 0, 0, 4, 5, 6]
splice();
지정한 범위까지의 index를 삭제, 추가로 매개변수를 입력하면 삭제한 위치에 아이템을 업데이트해줌
삭제된 아이템이 반환됨
const arr = ['a', 'b', 'c', 'd'];
let deleted = arr.splice(0, 2);
console.log(arr); //[ 'c', 'd' ]
console.log(deleted); //[ 'a', 'b' ]
여기까지 나온 함수들은 기존 배열을 업데이트하고
다음 나올 함수들은 기존 배열에 영향을 끼치지않고 새로운 배열을 반환한다.
slice();
시작하는 인덱스넘버, 입력한 범위를 매개변수로 한 item들을 배열로 만들어 반환한다.
- 인자없이 호출하면 배열 전체가 복제된다.
- 매개변수가 1개라면 시작하는 해당 인덱스넘버로 부터 끝까지 복제된다.
- index의 마지막 넘버는 -1 이며, 차례대로 절댓값을 올리면 뒤에서부터 카운트 된다.(범위지정은 작은 수 부터 해야함)
const arr = ['a', 'b', 'c', 'd'];
let sliced = arr.slice(0, 2);
console.log(arr); //['a', 'b', 'c', 'd']
console.log(sliced); //[ 'a', 'b' ]
let behind = arr.slice(-3, -1);
console.log(deleted); //[ 'b', 'c' ]
concat(); 여러개의 배열을 합쳐 반환한다. 호출 하는 방식을 잘 확인해보자.
reverse(); 순서가 거꾸로 뒤집한 배열을 반환한다.
const arr1 = ['a', 'b', 'c'];
const arr2 = ['d', 'e', 'f'];
let connected = arr1.concat(arr2);
console.log(connected); // [ 'a', 'b', 'c', 'd', 'e', 'f' ]
let reversed = connected.reverse();
console.log(reversed); // [ 'f', 'e', 'd', 'c', 'b', 'a' ]
flat();
중첩배열을 하나의 배열로 만들어 반환한다. 매개변수로는 중첩 단계를 입력할 수 있다. 비어있으면 1단계.
const arr = [
[1, 2, 3],
[4, ['a', 'b']]
];
console.log(arr); // [ [ 1, 2, 3 ], [ 4, [ 'a', 'b' ] ] ]
console.log(arr.flat()); // [ 1, 2, 3, 4, [ 'a', 'b' ] ]
console.log(arr.flat(2)); // [ 1, 2, 3, 4, 'a', 'b' ]
join();
배열의 모든 item을 콤마로 구분한 문자열로 반환한다.
매개변수로 입력한 값으로 콤마를 대체한다.
const arr = [1, 2, 3, 4, 5, 6];
console.log(arr.join()) // 1,2,3,4,5,6
console.log(arr.join('a')) // 1a2a3a4a5a6
다시말하지만 새로운 배열을 반환하는지 원본 배열을 수정하는지 잘 확인하고 사용하자