배열은 순서가 있는 값이다. 순서는 인덱스라고 부르며, 1이 아닌 0부터 번호를 매긴다.
대괄호(square bracket)를 이용해서 배열을 만들고, 각각의 원소(element)는 쉼표(comma)로 구분한다. 온점(dot)을 이용해서 변수가 가지고 있는 속성(property)에 접근할 수 있다.
배열은 생성하는 방법은 생성자 함수, 스택틱 함수, 배열리터럴 대괄호, 기존의 배열로부터 새로운 배열로 만드는 방법이 있다. 이 중에서 배열 리터럴 대괄호를 이용해서 변수에 할당하는 방법을 가장 많이 사용했다.
let array = new Array(3); // [ <3 empty items> ]
array = new Array(1, 2, 3); // [1, 2, 3]
array = Array.of(1, 2, 3); // [1, 2, 3]
const anotherArray = [1, 2, 3]; // [1, 2, 3];
array = Array.from(anotherArray); //[1, 2, 3];
const letter = Array.from( 'array' ) // [ 'a', 'r', 'r', 'a', 'y' ]
let myNumber = [73, 98, 86, 61];
myNumber[3]; // 61 (3번째 인덱스를 조회)
myNumber[3] = 100; // 3번째 인덱스의 값 변경 [73, 98, 86, 100]
myNumber.length; // 4
//배열 끝에 추가
myNumber.push(96); // [73, 98, 86, 100, 96]
// 배열 마지막 값 삭제
myNumber.pop(); // [73, 98, 86, 100]
myNumber.unshift(21); // [21, 73, 98, 86, 100]
myNumber.shift(); // [73, 98, 86, 100]
console.log(myNumber.indexOf(98)); //1 인덱스를 출력
number.indexOf(98) !==-1 //true
console.log(myNumber.includes(98)); //true
//1번째 인덱스 삭제
let spliceNumber = myNumber.splice(1, 1); // [73, 86, 100]
// 1번째 인덱스를 삭제하고 23, 12 추가
spliceNumber.splice(1, 1, 23, 12); [73, 23, 12, 86, 100]
-배열을 특정 인덱스부터 일정 구간만큼 제거하고 원하는 요소도 그 자리에 추가할 수 있음: split
(배열 자체를 수정)
let candies = "candy, chocolate, gummy bears";
candies.split(", ") // ['candy', 'chocolate', 'gummy bears']
let fruits = ["banana", "cherry", "mango", "kiwi"]
let newFruits = fruits.slice(0, 2); // ["banana", "cherry"]
anotherFruits = fruits.slice(-1); // ["kiwi"]
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = arr1.concat(arr2); //[1,2,3,4,5,6]
const arr4 = arr3.reverse(); //[6,5,4,3,2,1]
let number = [
[1, 2, 3],
[4, [5, 6, [3, 4]]],
];
number = number.flat(3); //[1,2,3,4,5,6,3,4]
// 특정한 값으로 배열을 채우기: fill
배열 자체를 수정한다.
number.fill(0); // [0,0,0,0,0,0,0,0]
number.fill('s', 1, 5); // [ 0, 's', 's', 's', 's', 0, 0, 0]
number.fill('a', 1); //[0, 'a', 'a', 'a','a', 'a', 'a', 'a']
let text = number.join(); //0,a,a,a,a,a,a,a
text = number.join(' | '); 0 | a | a | a | a | a | a | a
for(let n = 0; n < myNum.length; n++) {
console.log(myNum[n]);
}
let myNum = [10, 20, 40, 10];
let sum = 0;
for(n = 0; n < myNum.length; n++) {
sum = sum + myNum[n]
}
arr.length === 0
Array.isArray(myNum) //true
객체는 키와 값 쌍(key-value pair)으로 구성되며 키 값 사이는 콜론으로 구분된다. 객체는 Dot notation, Bracket notation으로 객체의 값을 사용할 수 있다.
let user = { firstName: 'mini', lastName: 'Lee' }
Dot notation
user.firstName; // 'mini'
Bracket notation
문자열로 작성하지 않을 경우에는 변수로 취급되니 주의해야 한다.
user['firstName'] // 'mini'
user['city'] = 'seoul';
delete user.city;
'firstName' in user; //true
function addPropertyAndValue(obj, property, value) {
obj[property] = value;
}
function allKeys(obj) {
for (let key in obj) {
console.log(key)
}
}
// 변수 greatest를 선언하고, 0번째 요소를 할당한다.
// 1번째 요소부터, 가장 마지막 요소까지 순회하는 반복문을 만든다.
// 만약, arr[i]가 greatest보다 크면, 변수 greatest에 arr[i]의 값을 할당한다.
// 그렇지 않으면, 아무런 동작도 하지 않는다.
// 반복문이 끝나면 변수 greatest를 리턴한다.
function getLargestElement(arr) {
let greatest = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > greatest) {
greatest = arr[i]
}
}
return greatest;
}
function extend(obj1, obj2) {
for (let key in obj2) {
if (!(key in obj1)) {
obj1[key] = obj2[key];
}
}
}
새롭게 생성된 배열은 원본 배열과 같은 요소를 갖지만 참조하고 있는 주소는 다르다.
let obj = { firstName: "jimin", lastName: "kim" };
let copiedObj1 = Object.assign({}, obj);
let copiedObj2 = {...obj};
이처럼 slice(), Object.assign(), spread syntax 등의 방법으로 참조 자료형을 복사하면, 중첩된 구조 중 한 단계까지만 복사합니다. 이것을 얕은 복사(shallow copy)라고 합니다.
참조 자료형 내부에 중첩되어 있는 모든 참조 자료형을 복사하는 것은 깊은 복사(deep copy)라고 합니다. 그러나 JavaScript 내부적으로는 깊은 복사를 수행할 수 있는 방법이 없습니다. 단, JavaScript의 다른 문법을 응용하면 깊은 복사와 같은 결과물을 만들어 낼 수 있습니다.
JSON.stringify()와 JSON.parse()
SON.stringify()는 참조 자료형을 문자열 형태로 변환하여 반환하고, JSON.parse()는 문자열의 형태를 객체로 변환하여 반환
중첩된 참조 자료형을 JSON.stringify()를 사용하여 문자열의 형태로 변환하고, 반환된 값에 다시 JSON.parse()를 사용하면, 깊은 복사와 같은 결과물을 반환합니다.
const arr = [1, 2, [3, 4]];
const copiedArr = JSON.parse(JSON.stringify(arr));
간단하게 깊은 복사를 할 수 있는 것처럼 보이지만, 이 방법 또한 깊은 복사가 되지 않는 예외가 존재합니다. 대표적인 예로 중첩된 참조 자료형 중에 함수가 포함되어 있을 경우 위 방법을 사용하면 함수가 null로 바뀌게 됩니다.
외부 라이브러리 사용
완전한 깊은 복사를 반드시 해야 하는 경우라면, node.js 환경에서 외부 라이브러리인 lodash, 또는 ramda를 설치하면 됩니다
const lodash = require('lodash');
const arr = [1, 2, [3, 4]];
const copiedArr = lodash.cloneDeep(arr);
console.log(arr); // [1, 2, [3, 4]]
console.log(copiedArr); // [1, 2, [3, 4]]
console.log(arr === copiedArr) // false
console.log(arr[2] === copiedArr[2]) // false
spread 문법
주로 배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때에 사용
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
sum(...numbers) // 6
rest 문법
파라미터를 배열의 형태로 받아서 사용할 수 있습니다. 파라미터 개수가 가변적일 때 유용
function sum(...theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
sum(1,2,3) // 6
sum(1,2,3,4) // 10
배열에서 사용하기
. 배열 합치기
let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];
// 질문: ['head', 'shoulders', 'knees', 'and', 'toes'];
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2]; // 참고: spread 문법은 기존 배열을 변경하지 않으므로(immutable), arr1의 값을 바꾸려면 새롭게 할당해야 합니다.
// 질문: arr1의 값은 무엇인가요?
spread 문법은 기존 배열을 변경하지 않으므로(immutable), 값을 바꾸려면 새롭게 할당해야 합니다.
객체에서 사용하기
let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
let clonedObj = { ...obj1 }; //{ foo: 'bar', x: 42 };
let mergedObj = { ...obj1, ...obj2 }; //{ foo: 'bar', x: 42, y: 13 };
함수에서 나머지 파라미터 받아오기
function myFun(a, b, ...manyMoreArgs) {
console.log("a", a); // a one
console.log("b", b); // b two
console.log("manyMoreArgs", manyMoreArgs); // ["three", "four", "five", "six"]
}
myFun("one", "two", "three", "four", "five", "six");
구조 분해 할당은 spread 문법을 이용하여 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정
const [a, b, ...rest] = [10, 20, 30, 40, 50];
const {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
객체에서 구조 분해 할당을 사용하는 경우, 선언(const, let, var)과 함께 사용하지 않으면 에러가 발생할 수 있습니다.
화살표 함수(arrow function)
function 키워드 대신 화살표(=>)를 사용
// 화살표 함수
const multiply = (x, y) => {
return x * y;
}
// 위 코드와 동일하게 동작합니다.
const square = ( x ) => { return x * x }
// 단, 매개변수가 없는 경우엔 소괄호를 생략할 수 없습니다.
const greeting = () => { return 'hello world' }
함수 코드 블록 내부가 하나의 문으로 구성되어 있다면 중괄호({})를 생략할 수 있다. 이때 코드 블록 내부의 문이 값으로 평가될 수 있으면 return 키워드를 생략할 수 있다.
const squre = x => x * x
// 위 코드와 동일하게 동작합니다.
const square = x => { return x * x }
// 위 코드와 동일하게 동작합니다.
const square = function (x) {
return x * x
}