배열의 생성
배열 리터럴
0개 이상의 값을 쉼표로 구분하여 대괄호로 묶는다. 첫번째 값은 인덱스 '0'으로 읽을 수 있다.
존재하지 않는 요소에 접근하면 undefined를 반환한다.
const arr = [];
console.log(arr[1]); //undefined
const arr = ['zero', 'one'];
console.log(arr[1]); // 'one'
console.log(typeof arr); //object
배열 리터럴은 객체 리터럴과 달리 프로퍼티명이 없고 각 요소의 값만이 존재한다.
객체는 프로퍼티 값에 접근하기 위해 대괄호 표기법 또는 마침표 표기법을 사용하며 프로퍼티명을 키로 사용한다.
배열은 요소에 접근하기 위해 대괄호 표기법만을 사용하며 대괄호 내에 접근하고자 하는 요소의 인덱스를 넣어준다.
두 객체의 근본적 차이는 배열 리터럴 arr의 프로토 타입 객체는 Array.prototype이지만 객체 리터럴 obj의 프로토타입 객체는 Object.prototype이라는 것이다.
const emptyArr = [];
const emptyObj = {};
console.dir(emptyArr.__proto__);
console.dir(emptyObj.__proto__);
대부분의 프로그래밍 언어에서 배열의 요소들은 모두 같은 데이터 타입이어야
하지만,
!! 자바스크립트 배열은 어떤 데이터 타입의 조합이라도 포함할 수 있다.
Array() 생성자 함수
배열은 일반적으로 배열 리터럴 방식으로 생성하지만, 배열 리터럴 방식도 결국 내장 함수 Array() 생성자 함수로 배열을 생성하는 것을
단순화 시킨 것이다.
Array()생성자 함수는 Array.prototype.constructor 프로퍼티로 접근할 수 있다.
Array() 생성자 함수는 매개변수의 갯수에 따라 다르게 동작한다.
매개변수가 1개이고 숫자인 경우, 매개변수로 전달된 숫자를 length 값으로 가지는 빈배열을 생성한다.
const arr = new Array(2);
console.log(arr); // [ <2 empty items> ]
const arr = new Array(1, 2, 3);
console.log(arr); // [1, 2, 3]
배열 요소의 추가와 삭제
배열 요소의 추가
객체가 동적으로 프로퍼티를 추가할 수 있는 것처럼 배열도 동적으로 요소를 추가할 수 있다.
이 때 순서에 맞게 값을 할당할 필요는 없고 인덱스를 사용하여 필요한 위치에 값을 할당한다.
배열의 길이는 마지막 인덱스를 기준으로 산정한다.
const arr = [];
console.log(arr[0]); // undefined
arr[1] = 1;
arr[3] = 3;
console.log(arr); // [ <1 empty item>, 1, <1 empty item>, 3 ]
console.log(arr.lenth); // 4
값이 할당되지 않은 인덱스 위치의 요소는 생성되지 않는다. 단, 존재하지 않는 요소를 참조하면 undefined가 반환된다.
배열 요소의 삭제
배열은 객체이기 때문에 배열의 요소를 삭제하기 위해 delete 연산자를 사용할 수 있다.
이 때, length에는 변함이 없다.
해당 요소를 완전히 삭제하여 lenth에도 반영되게 하기 위해서는 Array.prototype.splice 메소드를 사용한다.
const numbersArr = ["zero", "one", "two", "three"];
// 요소의 값만 삭제된다
delete numbersArr[2]; // [ 'zero', 'one', <1 empty item>, 'three' ]
console.log(numbersArr);
// 요소 값만이 아니라 요소를 완전히 삭제한다
// splice(시작 인덱스, 삭제할 요소수)
numbersArr.splice(2, 1); // ["zero", "one", "three"]
console.log(numbersArr);
배열의 순회
객체의 프로퍼티를 순회할 때 for...in 문을 사용한다. 배열 역시 객체이므로 for..in문을 사용할 수 있다.
그러나, 배열은 객체이기 때문에 프로퍼티를 가질 수 있다.
for..in 문을 사용하면 배열 요소뿐만 아니라 불필요한 프로퍼티까지 출력될수 있고 요소들의 순서를 보장하지 않으므로 배열을 순회하는데 적합하지 않다.
따라서, 배열의 순회에는 forEach 메소드, for문, for...of문을 사용하는 것이 좋다.
const arr = [0, 1, 2, 3];
arr.foo = 10;
for (const key in arr) {
console.log("key: " + key, "value: " + arr[key]);
}
// key: 0 value: 0
// key: 1 value: 1
// key: 2 value: 2
// key: 3 value: 3
// key: foo value: 10 => 불필요한 프로퍼티까지 출력
arr.forEach((item, index) => console.log(index, item));
// 0 0 1 1 2 2 3 3
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]); // 0 0 1 1 2 2 3 3
}
for (const item of arr) {
console.log(item); // 0 1 2 3
}
Array Property
Array.length
length 프로퍼티는 요소의 개수(배열의 길이)를 나타낸다.(2^32-1 미만)
const arr = [1,2,3,4,5];
console.log(arr.length); //5
주의할 것은 배열 요소의 개수와 length 프로퍼티의 값이 반드시 일치하지는 않는다는 것이다.
희소 배열이란 ? 배열 요소의 개수와 length 프로퍼티의 값이 일치하지 않는 배열이다.
희소 배열은 배열의 요소가 연속적이지 않은 배열을 의미한다. 희소 배열은 배열의 요소 개수보다 length 프로퍼티의 값이 언제나 크다.
희소 배열은 일반 배열보다 느리며 메모리를 낭비한다.
length 프로퍼티의 값은 명시적으로 변경할 수 있다.
만약, length 프로퍼티의 값을 현재보다 작게 변경하면 변경된 length 프로퍼티의 값보다 크거나 같은 인덱스에 해당하는 요소는 모두 삭제된다.
const arr = [ 1, 2, 3, 4, 5 ];
// 배열 길이의 명시적 변경
arr.length = 3;
console.log(arr); // [1, 2, 3]
Array Method
Array.prototype.push(...items):number
인수로 전달받은 모든 값을 원본 배열의 마지막에 요소로 추가하고 변경된 length를 반환한다. push 메소드는 원본배열을 직접 변경한다.
const arr = [1, 2];
// 인수로 전달받은 모든 값을 원본 배열의 마지막에 요소로 추가하고 변경된 length 값을 반환한다.
let result = arr.push(3, 4);
console.log(result); // 4
// push 메소드는 원본 배열을 직접 변경한다.
console.log(arr); // [1, 2, 3, 4]
push 메소드는 원본 배열을 직접 변경하지만, concat 메소드는 원본 배열을 변경하지 않고 새로운 배열을 반환한다.
push 메소드는 성능면에서 좋지 않다. push 메소드는 배열의 마지막에 요소를 추가하므로 length 프로퍼티를 사용하여 직접 요소를 추가할 수 있다.
!! 이 방법이 push 메소드보다 빠르다.
const arr = [1, 2];
// arr.push(3)와 동일한 처리를 한다. 이 방법이 push 메소드보다 빠르다.
arr[arr.length] = 3;
console.log(arr); // [1, 2, 3]
push 메소드는 원본 배열을 직접 변경하는 부수효과가 있다. 따라서 push 메소드 보다 spread 문법을 사용하는 편이 좋다.
const arr = [1, 2];
// ES6 spread 문법
const newArr = [...arr, 3];
// arr.push(3);
console.log(newArr); // [1, 2, 3]
Array.prototype.pop
원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환한다.
원본 배열이 빈 배열이면 undefined를 반환한다.
pop 메소드는 원본 배열을 직접 변경한다.
const arr = [1, 2];
// 원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환한다.
let result = arr.pop();
console.log(result); // 2
// pop 메소드는 원본 배열을 직접 변경한다.
console.log(arr); // [1]
Push + Pop -> Stack (LIFO)
// 스택 자료 구조를 구현하기 위한 배열
const stack = [];
// 스택의 가장 마지막에 데이터를 밀어 넣는다.
stack.push(1);
console.log(stack); // [1]
// 스택의 가장 마지막에 데이터를 밀어 넣는다.
stack.push(2);
console.log(stack); // [1, 2]
// 스택의 가장 마지막 데이터, 즉 가장 나중에 밀어 넣은 최신 데이터를 꺼낸다.
let value = stack.pop();
console.log(value, stack); // 2 [1]
// 스택의 가장 마지막 데이터, 즉 가장 나중에 밀어 넣은 최신 데이터를 꺼낸다.
value = stack.pop();
console.log(value, stack); // 1 []
Array.prototype.reverse()
배열 요소의 순서를 반대로 변경한다. 이 때, 원본 배열이 변경된다. 반환값은 변경된 배열이다.
const a = ['a', 'b', 'c'];
const b = a.reverse();
// 원본 배열이 변경된다
console.log(a); // [ 'c', 'b', 'a' ]
console.log(b); // [ 'c', 'b', 'a' ]
Array.prototype.shift()
배열에서 첫 요소를 제거하고 제거한 요소를 반환한다. 만약, 빈 배열일 경우 undefined를 반환한다.
shift 메소드는 대상 배열 자체를 변경한다.
const a = ['a', 'b', 'c'];
const c = a.shift();
// 원본 배열이 변경된다.
console.log(a); // a --> [ 'b', 'c' ]
console.log(c); // c --> 'a'
shift + push -> queue(FIFO)
const arr = [];
arr.push(1); // [1]
arr.push(2); // [1, 2]
arr.push(3); // [1, 2, 3]
arr.shift(); // [2, 3]
arr.shift(); // [3]
arr.shift(); // []
Array.isArray(arg:any):boolean
정적 메소드 Array.isArray는 주어진 인수가 배열이면 true, 아니면 false를 반환한다.
// true
Array.isArray([]);
Array.isArray([1, 2]);
Array.isArray(new Array());
// false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(1);
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.from
ES6에 새롭게 도입된 Array.from 메소드는 유사 배열 객체(array-like object) 또는 이터러블 객체(iterable object)를 변환하여 새로운 배열을 생성한다.
// 문자열은 이터러블이다.
const arr1 = Array.from('Hello');
console.log(arr1); // [ 'H', 'e', 'l', 'l', 'o' ]
// 유사 배열 객체를 새로운 배열을 변환하여 반환한다.
const arr2 = Array.from({ length: 2, 0: 'a', 1: 'b' });
console.log(arr2); // [ 'a', 'b' ]
// Array.from의 두번째 매개변수에게 배열의 모든 요소에 대해 호출할 함수를 전달할 수 있다.
// 이 함수는 첫번째 매개변수에게 전달된 인수로 생성된 배열의 모든 요소를 인수로 전달받아 호출된다.
const arr3 = Array.from({ length: 5 }, function (v, i) { return i; });
console.log(arr3); // [ 0, 1, 2, 3, 4 ]
Array.of
ES6에서 새롭게 도입된 Array.of 메소드는 전달된 인수를 요소로 갖는 배열을 생성한다.
Array.of는 Array 생성자 함수와 다르게 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
const arr = new Array(2);
console.log(arr); // [ <2 empty items> ]
// 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
const arr1 = Array.of(1);
console.log(arr1); // // [1]
const arr2 = Array.of(1, 2, 3);
console.log(arr2); // [1, 2, 3]
const arr3 = Array.of('string');
console.log(arr3); // 'string'
Array.prototype.indexOf(searchElement: T, fromIndex?:number):number
원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환한다.
- 중복된 요소가 있는 경우 : 첫번째 인덱스를 반환한다.
- 해당 요소가 없는 경우 : -1을 반환한다.
const arr = [1, 2, 2, 3];
// 배열 arr에서 요소 2를 검색하여 첫번째 인덱스를 반환
arr.indexOf(2); // -> 1
// 배열 arr에서 요소 4가 없으므로 -1을 반환
arr.indexOf(4); // -1
// 두번째 인수는 검색을 시작할 인덱스이다. 두번째 인수를 생략하면 처음부터 검색한다.
arr.indexOf(2, 2); // 2
indexOf 메소드는 배열에 요소가 존재하는 지 여부를 확인할 때 유용하다.
const foods = ['apple', 'banana', 'orange'];
// foods 배열에 'orange' 요소가 존재하는지 확인
if (foods.indexOf('orange') === -1) {
// foods 배열에 'orange' 요소가 존재하지 않으면 'orange' 요소를 추가
foods.push('orange');
}
console.log(foods); // ["apple", "banana", "orange"]
Array.prototype.concat(...items:Array)
인수로 전달된 값들을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환한다. 원본 배열은 변경되지 않는다.
const arr1 = [1, 2];
const arr2 = [3, 4];
// 배열 arr2를 원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
// 인수로 전달한 값이 배열인 경우, 배열을 해체하여 새로운 배열의 요소로 추가한다.
let result = arr1.concat(arr2);
console.log(result); // [1, 2, 3, 4]
// 숫자를 원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
result = arr1.concat(3);
console.log(result); // ["1, 2, 3]
// 배열 arr2와 숫자를 원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
result = arr1.concat(arr2, 5);
console.log(result); // [1, 2, 3, 4, 5]
// 원본 배열은 변경되지 않는다.
console.log(arr1); // [1, 2]
Array.prototype.join(separator?:string):string
원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달 받은 값. 즉, 구분자로 연결한 문자열을 반환한다.
구분자는 생략가능하며 기본 구분자는 ","이다. 원본 배열은 변경되지 않는다.
const arr = [1, 2, 3, 4];
// 기본 구분자는 ','이다.
// 원본 배열 arr의 모든 요소를 문자열로 변환한 후, 기본 구분자 ','로 연결한 문자열을 반환
let result = arr.join();
console.log(result); // '1,2,3,4';
// 원본 배열 arr의 모든 요소를 문자열로 변환한 후, 빈문자열로 연결한 문자열을 반환
result = arr.join('');
console.log(result); // '1234'
// 원본 배열 arr의 모든 요소를 문자열로 변환한 후, 구분자 ':'로 연결한 문자열을 반환
result = arr.join(':');
console.log(result); // '1:2:3:4'
console.log(arr); //[1, 2, 3, 4]
Array.prototype.slice(start?:number, end?:number)
인자로 지정된 배열의 부분을 복사하여 반환한다. 원본 배열은 변경되지 않는다.
const items = ['a', 'b', 'c'];
// items[0]부터 items[1] 이전(items[1] 미포함)까지 반환
let res = items.slice(0, 1);
console.log(res); // [ 'a' ]
// items[1]부터 items[2] 이전(items[2] 미포함)까지 반환
res = items.slice(1, 2);
console.log(res); // [ 'b' ]
// items[1]부터 이후의 모든 요소 반환
res = items.slice(1);
console.log(res); // [ 'b', 'c' ]
// 인자가 음수인 경우 배열의 끝에서 요소를 반환
res = items.slice(-1);
console.log(res); // [ 'c' ]
res = items.slice(-2);
console.log(res); // [ 'b', 'c' ]
// 모든 요소를 반환 (= 복사본(shallow copy) 생성)
res = items.slice();
console.log(res); // [ 'a', 'b', 'c' ]
// 원본은 변경되지 않는다.
console.log(items); // [ 'a', 'b', 'c' ]
slice 메소드에 인자를 전달하지 않으면 원본 배열의 복사본을 생성하여 반환한다.
const arr = [1, 2, 3];
// 원본 배열 arr의 새로운 복사본을 생성한다.
const copy = arr.slice();
console.log(copy, copy === arr); // [ 1, 2, 3 ] false
Array.prototype.splice(start:numbere, deletecount=this.length-start, ...items)
기존의 배열의 요소를 제거하고 그 위치에 새로운 요소를 추가한다.
배열 중간에 새로운 요소를 추가할 때 사용한다.
원본 배열이 변경된다.
start : start만 지정하면 start부터 모든 요소를 제거한다.
deleteCount : start부터 제거할 요소의 수다. 0일 경우, 아무런 요소도 제거되지 않는다.
items : 삭제한위치에 추가할 요소이다. 지정하지 않을 경우, 삭제만 한다.
const items1 = [1, 2, 3, 4];
// items[1]부터 2개의 요소를 제거하고 제거된 요소를 배열로 반환
const res1 = items1.splice(1, 2);
// 원본 배열이 변경된다.
console.log(items1); // [ 1, 4 ]
// 제거한 요소가 배열로 반환된다.
console.log(res1); // [ 2, 3 ]
const items2 = [1, 2, 3, 4];
// items[1]부터 모든 요소를 제거하고 제거된 요소를 배열로 반환
const res2 = items2.splice(1);
// 원본 배열이 변경된다.
console.log(items2); // [ 1 ]
// 제거한 요소가 배열로 반환된다.
console.log(res2); // [ 2, 3, 4 ]
다른 요소 빼고 집어 넣기
const items = [1, 2, 3, 4];
// items[1]부터 2개의 요소를 제거하고 그자리에 새로운 요소를 추가한다. 제거된 요소가 반환된다.
const res = items.splice(1, 2, 20, 30);
// 원본 배열이 변경된다.
console.log(items); // [ 1, 20, 30, 4 ]
// 제거한 요소가 배열로 반환된다.
console.log(res); // [ 2, 3 ]
중간에 다른 요소 집어 넣기
const items = [1, 4];
items.splice(1, 0, ...[2, 3]); //[ 1, 2, 3, 4 ]
console.log(items);
!!slice는 배열의 일부분을 복사해서 반환하며 원본을 훼손하지 않는다.
splice는 배열에서 요소를 제거하고 제거한 위치에 다른 요소를 추가하며 원본을 훼손한다.
'Javscript' 카테고리의 다른 글
[Javascript] 자바스크립트 메소드, 프로퍼티 (1/28) (0) | 2022.01.29 |
---|---|
[Javascript] 다른 언어 배열들과의 차이점, 장단점 (1/28) (0) | 2022.01.29 |
[Javascript] String 객체 (1/27) (0) | 2022.01.29 |
[Javascript] 정규식 (1/21) (0) | 2022.01.21 |
[Javascript] Date 객체 (1/21) (0) | 2022.01.21 |