자바스크립트에서 배열을 만드는 방법은 크게 2가지가 있다.
- 배열 리터럴 대괄호[]를 사용하여 만드는 방법
- Array() 생성자 함수로 배열을 생성하는 방법
배열 리터럴 대괄호[]를 사용
// 빈 배열 생성
var arr = [];
arr[0] = "zero";
arr[1] = "one";
arr[2] = "two";
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// zero
// one
// two
}
// 초기값 할당 배열
var arr = ["zero", "one", "tow"];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// zero
// one
// two
}
// 배열 생성 (배열 크기 지정)
// 쉼표 개수만큼 크기가 지정됨
var arr = [, , ,];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// undefined
// undefined
// undefined
}
Array() 생성자 함수로 배열을 생성하는 방법
// 배열 생성 (빈 배열)
var arr = new Array();
arr[0] = "zero";
arr[1] = "one";
arr[2] = "tow";
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// zero
// one
// two
}
// 배열 생성 (초기 값 할당)
var arr = new Array("zero", "one", "tow");
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// zero
// one
// two
}
// 배열 생성 (배열 크기 지정)
// 원소가 1개이고 숫자인 경우 배열 크기로 사용됨
var arr = new Array(3);
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
// undefined
// undefined
// undefined
}
다른 언어와의 다른 점 2가지
- 배열 내부의 데이터 타입이 서로 다를 수 있다.
- 배열 크기는 동적으로 변경될 수 있다.
// 서로 다른 데이터 타입을 담을 수 있다
var arr = [1234, "test", true];
// 배열의 크기를 임의로 변경( 3 -> 5 )
// arr[3], arr[4]는 값이 할당 되지 않았기 때문에 undefined
arr.length = 5;
// 새로운 배열을 추가하면 크기는 자동으로 변경 ( 5 -> 6 )
arr[5] = "apple";
// 새로운 배열 추가로 크기 변경 ( 6 -> 7 )
arr.push("banana");
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
/* 1234
test
true
undefined
undefined
apple
banana */
}
분류 | 메서드 | 설명 |
---|---|---|
수정메서드 | fill(value, begin, end) | begin~end-1 사이의 요소를 target으로 대체함 |
pop() | 배열의 마지막 요소를 잘라냄 | |
push() | 배열 끝에 data를 추가 | |
reverse() | 배열 요소를 역순으로 정렬 | |
sort([callback]) | 배열 요소를 callback이 구현한 방법에 따라 정렬 | |
splice(index, howmany [, data ...] | index부터 howmany개의 배열 요소를 data로 대체 | |
====== | ============== | =========================== |
접근자 메서드 | concat(arra) | 지정한 배열을 대상 배열에 연결 |
indexOf(data,index) | data와 같은 첫 번째 배열 요소의 키를 검색 | |
join(string) | 배열의 요소를 string으로 연결한 문자열 반환 | |
slice(begin, [, end]) | begin~end-1 사이의 요소를 제거한 새로운 배열을 반환 | |
toLocalString() | 배열의 요소를 해당 지역에 맞는 언어로 번역한 문자열로 변환한 뒤 쉼표로 연결해서 반환 | |
toString() | 배열의 요소를 문자열로 변환 후 쉼표로 연결해서 반환 | |
====== | ============== | =========================== |
반복 메서드 | entries | 배열 요소의 인덱스와 값이 요소로 들어 있는 배열을 값으로 반환하는 이터레이터를 반환 |
filter(callback) | callback 조건에 부합하는 배열 요소만 담은 새로운 배열을 생성함 | |
find(callback [,thisArg]) | callback 조건에 부합하는 첫 번째 배열 요소를 반환 | |
forEach(callback [,thisArg]) | 배열의 요소를 callback을 사용하여 차례대로 처리함 | |
keys() | 배열 요소의 인덱스를 값으로 가지는 이터레이터를 반환 | |
reduce(callback[,initial]) | 이웃한 배열 요소를 배열의 왼쪽부터 차례대로 callback으로 처리하여 하나의 값으로 만들어 반환 |
push 메서드
var a = ["A", "B", "C"];
a.push("D"); // ["A","B","C","D"] 반환값 = 4
a.push("E", "F"); // ["A","B","C","D","E","F"]
pop 메서드
var a = ["A", "B", "C"];
a.push(); // ["A","B"] 반환값 = "C"
shift 메서드
var a = ["A", "B", "C"];
a.shift(); // ["B","C"] 반환값 = "A"
unshift 메서드
var a = ["A", "B", "C"];
a.shift("X"); // ["X","A","B","C"] 반환값 = 4
a.shift("Y", "Z"); // ["Y","Z","X","A","B","C"];
splice 메서드
첫번째 인수 : 배열을 수정하기 시작할 위치를 가리키는 인덱스
두번째 인수 : 배열에서 삭제할 요소의 개수
세번째 이후의 인수 : 배열에 삽입할 요소의 값을 쉼표로 구분해서 넘김
var a = ["A", "B", "C", "D"];
a.splice(1, 2, "X", "Y", "Z"); // ["A", "X", "Y", "Z", "D"]; 반환값 = ["B","C"]
// 첫번째 인수만 넘길 시
var a = ["A", "B", "C", "D"];
a.splice(2); // ["A","B"]; 반환값 = ["C","D"]
// 첫번째 인수가 음수일 시
var a = ["A", "B", "C", "D", "E", "F"];
a.splice(-1); // ["A","B","C"]; 반환값 = ["D"]
// 두번째 인수가 0일 시
var a = ["A", "B", "C", "D"];
a.splice(1, 0, "X", "Y"); // ["A","X","Y","B","C","D"] 반환값 = []
sort 메서드
var a = [5, 2, 7, 1, 3, 9, 8];
a.sort(function (a, b) {
return a - b;
// function(a,b) < 0 이면 a를 b보다 작은 인덱스로 정렬
// function(a,b) == 0 이면 순서를 바꾸지 않는다
// function(a,b) > 0 이면 b를 a보다 작은 인덱스로 정렬
}); // [1,2,3,5,7,8,9]
// 객체 배열을 특정 프로퍼티의 값으로 정렬하기
function compaireFunc(key) {
return function (a, b) {
return a[key] - b[key];
};
}
var persons = [
{ name: "Tom", age: 17 },
{ name: "Huck", age: 18 },
{ name: "Becky", age: 16 },
];
persons.sort(compaireFunc("age"));
/*[
{ name: 'Becky', age: 16 },
{ name: 'Tom', age: 17 },
{ name: 'Huck', age: 18 }
]*/
접근자 메서드는 배열을 다른 모습으로 가공한 새로운 배열을 반환한다.
join 메서드
var a = ["A", "B", "C"];
a.join("-"); // "A-B-C"
a.join(""); // "ABC"
concat 메서드
concatenate의 줄임말로 "연결하다"라는 단어의 줄임말
var a = ["A", "B", "C"];
a.concat(["D", "E"]); // ["A","B","C","D","E"]
a.concat(["D", "E"], ["F", "G"]); // ["A","B","C","D","E","F","G"]
a.concat(1, "X", true); // ["A","B","C",1,"X",true]
a.concat("D", ["E", ["F", "G"]]); // ["A","B","C","D","E",["F","G"]]
slice 메서드
var a = ["A", "B", "C", "D", "E"];
a.slice(1, 3); // ["B","C"]
// 두번째 인수 생략 시
a.slice(3); // ["D","E"]
// 인수가 음수일 시
a.slice(1, -1); // ["B","C","D"]
a.slice(-3, -2); // ["C"]
indexOf와 lastIndexOf 메서드
인수로 지정한 값을 검색해서 찾은 요소를 반환한다. 찾지 못했을 때는 -1 반환
var a = ["A", "B", "C", "C", "E"];
// 가장 작은 인덱스 부터 검색
a.indexOf("C"); // 2
// 가장 큰 인덱스 부터 검색
a.lastIndex("C"); // 3
// 두 번째 인수로 검색을 시작할 인덱스를 넘기는 예
a.indexOf("C", 3); // 3
toString과 toLocaleString 메서드
배열 요소를 쉼표로 구분한 문자열로 반환, toLocaleString 메서드는 해당 지역에 맞는 언어로 번역한 문자열 반환
["A", "B", "C", date].toString();
[1, 2, 3, date].toString();
[1, [2, 3], date].toString();
var date = new Date();
console.log(["A", "B", "C", date].toString()); // "A,B,C, Wed Jan ~~~ "
console.log(["A", "B", "C", date].toLocaleString()); // "A,B,C, 2021.05.05 오후 ~~"
배열의 모든 요소를 순회하며 조건을 만족하는 요소를 가져올 때 사용
반복 메서드 공통적인 성질
첫번째 인수 : 현재 처리하고 있는 배열 요소의 값
두번째 인수 : 현재 처리하고 있는 배열 요소의 인덱스
세번째 인수 : 메서드가 적용되는 배열의 참조
forEach 메서드
var a = [1, 2, 3, 4, 5];
var sum = 0;
a.forEach(function (value) {
sum += value;
});
console.log(sum); // 15
a.forEach(function (value, index, array) {
array[index] = value * value;
});
console.log(a);
map 메서드
인수로 받은 함수를 배열의 요소별로 한 번씩 실행하며, 마지막에는 그 함수가 반환한 값으로 새로운 배열을 생성한다.
var a = [1, 2, 3, 4, 5];
var b = a.map(function (x) {
return 2 * x; // b = [2,4,6,8,10]
});
// 객체 배열의 요소를 순회
var persons = [
{ name: "Tom", age: 17 },
{ name: "Huck", age: 18 },
{ name: "Becky", age: 16 },
];
var names = persons.map((person) => person.name);
var ages = persons.map((person) => person.age);
console.log(names); // [ 'Tom', 'Huck', 'Becky' ]
console.log(ages); // [ 17, 18, 16 ]
reduce 메서드
배열의 첫 번재 요소부터 마지막 요소까지의 합성 곱을 처리한다.
합성 곱
이란 배열 요소 하나를 함수로 처리한 후에 그 반환값을 다음 번 요소를 처리할 때 함수의 입력 값으로 사용하는 처리 방법
reduce 메서드 인수
callback : 합성 곱을 하는 함수
initial : callback이 처음 호출되었을 때의 첫 번째 인수 (생략 가능)
callback 함수 인수
prev : 이전 요소를 처리한 함수의 반환값 or initial or 첫 번재 요소의 값
value : 현재 처리하는 배열 요소의 값
index : 현재 처리하는 배열 요소의 인덱스
array : 메서드를 적용 중인 배열의 참조
initial 지정 여부에 따라 callback 인수 값들이 바뀜
initial 지정 : prev는 initial의 값, value는 배열의 첫 번째 요소, index는 0
initial 지정 X : prev는 배열의 첫 번째 요소의 값, value는 배열의 두 번째 요소 값, index는 1
// 배열 요소의 합
var a = [1, 2, 3, 4, 5];
a.reduce(function (prev, value) {
return prev + value;
}, 0); // 15 (initial 지정)
a.reduce(function (prev, value) {
return prev + value;
}); // 15 (initial 지정 X)
// 배열 요소의 곱과 최댓값
var a = [1, 2, 3, 4, 5];
a.reduce(function (prev, value) {
return prev * value; // 120 (배열 곱)
}, 1);
a.reduce(function(prev, value) {
return (prev>value ? prev:value); // 5 (배열의 최댓값)
}
// 배열 안의 모든 순열 목록 구하기
function perm(a) {
// 순열 목록(list)을 각 순열의 요소(element)로 추가하면서 갱신해 나간다
return a.reduce(
function (list, element) {
var newlist = []; // 새로운 순열 목록 저장하는 배열
// 각 순열(seq)별로 처리
list.forEach(function (seq) {
// seq 배열 끝에서 두번째, 앞에서 두번째 요소에 이르기까지 차례로 element 삽입
// 그 후 newlist에 추가
for (var i = seq.length; i >= 0; i--) {
var newseq = [].concat(seq);
newseq.splice(i, 0, element); // newseq의 i번째 요소 앞에 element 삽입
newlist.push(newseq); // newseq을 newlist의 끝에 추가
}
});
return newlist;
},
[[]] // 초깃값 (빈 배열이 저장된 배열)
);
}
var a = [1, 2, 3];
perm(a).forEach(function (v) {
console.log(v);
});
/*
[ 1, 2, 3 ]
[ 1, 3, 2 ]
[ 3, 1, 2 ]
[ 2, 1, 3 ]
[ 2, 3, 1 ]
[ 3, 2, 1 ]
*/
배열에 배열을 중첩하여 다차원 배열과 비슷한 기능을 구현할 수 있다.
// 2차원 배열을 생성
var x = new Array(3);
for (var i = 0; i < 3; i++) {
x[i] = new Array(3);
}
// 2차원 배열에 값을 대입
for (var count = 1, i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
x[i][j] = count++;
}
("\n");
}
console.log(x);
// 배열 리터럴
var x = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
크기가 3x3인 모든 마방진 구하기
function perm(a) {
// 순열 목록(list)을 각 순열의 요소(element)로 추가하면서 갱신해 나간다
return a.reduce(
function (list, element) {
var newlist = []; // 새로운 순열 목록 저장하는 배열
// 각 순열(seq)별로 처리
list.forEach(function (seq) {
// seq 배열 끝에서 두번째, 앞에서 두번째 요소에 이르기까지 차례로 element 삽입
// 그 후 newlist에 추가
for (var i = seq.length; i >= 0; i--) {
var newseq = [].concat(seq);
newseq.splice(i, 0, element); // newseq의 i번째 요소 앞에 element 삽입
newlist.push(newseq); // newseq을 newlist의 끝에 추가
}
});
return newlist;
},
[[]] // 초깃값 (빈 배열이 저장된 배열)
);
}
var N = 3;
// 1부터 N*N의 요소를 가진 배열 a를 생성
for (var i = 1, a = []; i <= N * N; i++) {
a = a.concat(i);
}
// N*N인 2차원 배열 생성
var m = new Array(N);
for (var i = 0; i < N; i++) {
m[i] = new Array(N);
}
// a의 순열을 생성하고 각각의 순열 p로 2차원 배열 m을 만든다. 그리고 마방진인지 판정
perm(a).forEach(function (p) {
for (var i = 0, index = 0; i < N; i++) {
for (var j = 0; j < N; j++) {
m[i][j] = p[index++];
}
}
// 마방진이면 출력
if (isMagicSquare(m)) {
m.forEach(function (v) {
console.log(v);
});
console.log("------");
}
});
// 마방진인지 판정
function isMagicSquare(m) {
var n = m.length;
var isMagic = (n * (n * n + 1)) / 2; // 행, 열, 대각선의 합이 이 값일 경우 마방진
var sumR = 0; // 오른쪽 대각선 방향 합
var sumL = 0; // 왼쪽 대각선 방향 합
for (var i = 0; i < n; i++) {
var sumRow = 0;
var sumColumn = 0;
for (var j = 0; j < n; j++) {
sumRow += m[i][j];
sumColumn += m[j][i];
}
if (sumRow != isMagic || sumColumn != isMagic) return false;
sumR += m[i][i];
sumL += m[i][n - i - 1];
}
if (sumR != isMagic || sumL != isMagic) return false;
return true;
}
/*
[ 6, 1, 8 ]
[ 7, 5, 3 ]
[ 2, 9, 4 ]
------
[ 8, 1, 6 ]
[ 3, 5, 7 ]
[ 4, 9, 2 ]
------
[ 8, 3, 4 ]
[ 1, 5, 9 ]
[ 6, 7, 2 ]
------
[ 4, 3, 8 ]
[ 9, 5, 1 ]
[ 2, 7, 6 ]
------
[ 6, 7, 2 ]
[ 1, 5, 9 ]
[ 8, 3, 4 ]
------
[ 2, 7, 6 ]
[ 9, 5, 1 ]
[ 4, 3, 8 ]
------
[ 2, 9, 4 ]
[ 7, 5, 3 ]
[ 6, 1, 8 ]
------
[ 4, 9, 2 ]
[ 3, 5, 7 ]
[ 8, 1, 6 ]
*/
3차원 배열은 중첩된 배열의 배열로 표기해서 만들 수 있다.
// 3차원 배열 생성
var x = new Array(3);
for (var i = 0; i < 3; i++) {
x[i] = new Array(3);
for (var j = 0; j < 3; j++) {
x[i][j] = new Array(3);
}
}
// 3차원 배열에 값 대입
for (var count = 1, i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
x[i][j] = count++;
}
}
자바스크립트에서 배열이란 곧 Array 타입의 객체를 말한다. Array 타입의 객체는 다음과 같은 성질이 있다.
- 0 이상의 정수 값을 프로퍼티 이름으로 갖는다.
- length 프로퍼티가 있으며 그에 따라 배열 크기가 변한다.
- 프로토타입이 Array.prototype 이므로 Array.prototype의 메서드를 상속받아서 사용 가능하다.
이런 성질 중에서 프로퍼티 이름이 0 이상의 정수이며 length 프로퍼티가 있는 객체는 대부분 배열로 다룰 수 있다. 이러한 객체를 유사 배열 객체
라고 한다.
유사 배열 객체는 다음과 같은 방법으로 생성가능하다.
// 유사 배열 객체를 생성해서 값을 대입
var a = {};
for (var i = 0; i < 10; i++) {
a[i] = i;
}
a.length = 10;
// 유사배열 객체 요소의 합을 구한다.
for (var i = 0, sum = 0; i < a.length; i++) sum += a[i];
console.log(sum);
유사배열 객체는 배열로 참조하거나 대입할 수 있고 for, for/in 문으로 반복처리가 가능하다. 그러나 요소의 추가와 삭제 또는 length 프로퍼티 값 등 배열처럼 동작하지는 않는다.
유사 배열 객체는 Array.prototype의 메서드를 직접 사용할 수 없지만 Function.prototype.call 메서드로 간접호출하여 사용할 수 있다.
var a = { 0: "A", 1: "B", 2: "C", length: 3 };
Array.prototype.join.call(a, ","); // -> "A,B,C"
Array.prototype.push.call(a, "D"); // -> "{0:"A", 1:"B", 2:"C", 3:"D", length:4}
Array.prototype.slice.call(a, 0); // -> ["A","B","C","D"] 진짜 배열로 변환
var a = { 0: 1, 1: 2, 2: 3, length: 3 };
Array.prototype.map.call(a, function (v) {
return v * v;
}); // [1,4,9]
var a = { 0: 1, 1: 2, 2: 3, length: 3 };
Array.prototype.concat.call(a, ["D", "E"]);
// -> [{0:"A", 1:"B", 2:"C", length:3}, "D","E"]
비구조화 할당은 배열, 객체, 반복 가능 객체에서 값을 꺼내어 그 값을 별도의 변수에 대입하는 문장이다.
배열의 비구조화 할당
var [a, b] = [1, 2]; // a = 1, b = 2 와 같음
[a, b] = [2 * a, 3 * b]; // a = 2*a, b = 3*b
[a, b] = [b, a]; // a 와 b 값을 교환
[a, b, c] = [1, 2]; // a = 1, b = 2, c = undefined
[a, b] = [1, 2, 3]; // a = 1, b = 2, 3은 무시됨
[, a, , b] = [1, 2, 3, 4]; // a = 2, b = 4와 같음
var array, first, second;
array = [first, second] = [1, 2, 3, 4];
// first = 1, second = 2, array = [1,2,3,4]와 같음
[a, b, ...rest] = [1, 2, 3, 4]; // a = 2, b = 2, rest = [3,4];
[a = 0, b = 1, c = 2] = [1, 2]; // a = 1, b = 2, c = 2 와 같음
function rotation(x, y, theta) {
var s = Math.sin(theta),
c = Math.cos(theta);
return [c * x - s * y, s * x + c * y];
}
var [a, b] = rotation(1, 2, Math.PI / 3);
객체의 비구조화 할당
위의 배열처럼 객체도 비구조화 할당 할 수 있다. (배열이냐 객체냐의 문제라 생략하도록 하겠다.😅)
반복 가능한 객체의 비구조화 할당
var [a,b,c] = "ABC"; // a = "A", b = "B", c = "C";
function* createNumbers(from, to) {
while(from <= to) yield from++;
}
var [a,b,c,d,e] = createNumbers(10,15);
// a = 10, b = 11, c = 12, d = 13, e = 14
중첩된 자료 구조의 비구조화 할당
var [a,[b,c]] = [1,[2,3]]; // var a = 1, b = 2, c = 3;
var {a:x, b : {c:y, d:z}} = {a:1, b:{c:2,d:3}}; // x = 1, y = 2, z = 3
...은 전개 연산자
라고 한다. 전개 연산자
는 반복 가능한 객체를 반환하는 표현식 앞에 표기하며, 이를 통해 반복 가능한 객체를 배열 리터럴 또는 함수의 인수 목록으로 펼칠 수 있다.
var a = [..."ABC"]; // a -> ["A","B","C"]
f(..."ABC") // f("A","B","C")
var a = ["A","B","C"];
a.push(...["D","E"]); // ["A","B","C","D","E"];
var a = [5,2,3,6,1];
Math.max(...a); // 6