구조 분해 할당이란 배열이나 객체에서 요소를 해체하여 개별 변수에 그 값을 담을 때 사용합니다.
- 배열의 구조 분해 할당
: 배열의 값을 순서대로 변수를 할당합니다.
let arr = [1, 2, 3];
let [one, two, three] = arr;
특징
- 객체의 구조 분해 할당
: 프로퍼티의 value 값을 변수에 할당합니다.
let person = { // 객체 생성
name: "이정환",
age: 25,
location: "경기도"
};
let { name, age, location } = person;
특징
- 함수의 매개변수가 객체일 때 구조 분해 할당
: 전달된 객체에서 프로퍼티의 value를 매개변수에 각각 구조 분해 할당합니다.
function func({ name, age, location }) {
console.log(name, age, location);
}
// 매개변수 이름 변경
function func({ name: n, age: a, location: l }) {
console.log(n, a, l);
}
특징
- 스프레드 연산자 ( = 전개 연산자 )
배열, 문자열, 객체 등 반복이 가능한 객체의 값을 개별 요소로 분리합니다. → ‘ … ‘ 기호 사용
// 배열
let arrA = [1, 2, 3];
let arrB = [...arrA, 4, 5, 6];
// [1, 2, 3, 4, 5, 6] 출력
// 스프레드 연산자 사용x -> [[1, 2, 3], 4, 5, 6] 출력
// 객체
let objA = {
a : 1,
b : 2
};
let objB = {
...objA,
c : 3,
d : 4
};
// {a: 1, b: 2, c: 3, d: 4}출력
// 함수
function func(a, b, c) {
console.log(a, b, c);
}
let arr = [1, 2, 3];
func(...arr);
// 1 2 3 출력
++ 매개변수와 구조 분해 할당의 차이점
구조 분해 할당 : 전달하는 인수 1개이며 그 값이 객체여야 합니다.
스프레드 연산자 : 인수가 여러 개로 나뉘어 전달하므로 매개변수를 여러 개 선언해야 한다는 차이가 있습니다.
- rest 매개변수 ( = 나머지 매개변수 )
개별 요소를 순차적으로 배열에 저장해 묶습니다. → 매개변수 앞에 ‘ ... ‘ 을 기호를 붙여 사용합니다.
function func(...rest) {
console.log(rest);
}
func(1, 2, 3, 4);
// [1, 2, 3, 4] 출력
// 매개변수와 함께 사용시
function func(p, ...rest) {
console.log(p);
console.log(rest);
}
func(1, 2, 3, 4);
// 1 츨력
// [2, 3, 4] 츨력
++ 매개변수와 함께 사용시 주의 사항
rest 매개변수는 나머지 값을 모두 배열에 저장하므로 마지막에 선언해야 합니다.
인수는 왼쪽에서 오른쪽 방향으로 순차적으로 할당하기에 다른 매개변수에 값을 할당하기 위해선 rest 매개변수를 마지막에 작성해야 합니다.
배열 메서드
자바스크립트에서 배열을 쉽게 다를 수 있도록 제공하는 여러 메서드입니다.
- 요소의 추가와 삭제 메서드
let food = ["짜장면", "피자", "치킨"];
const newLength = food.push("탕수육", "라자냐");
console.log(food); // ["짜장면", "피자", "치킨", "탕수육", "라자냐"] 출력
console.log(`새로운 배열의 길이: ${newLength}`); // 새로운 배열의 길이: 5
let food = ["짜장면", "피자", "치킨"];
const removedItem = food.pop();
console.log(removedItem); // 치킨
console.log(food); // ["짜장면", "피자"]
let food = ["짜장면", "피자", "치킨"];
const newLength = food.unshift("갈비찜");
console.log(food); // ["갈비찜", "짜장면", "피자", "치킨"]
console.log(`새로운 배열의 길이: ${newLength}`); // 새로운 배열의 길이: 4
let food = ["짜장면", "피자", "치킨"];
const removedItem = food.shift();
console.log(removedItem); // "짜장면"
console.log(food); // ["피자", "치킨"]
++ push와 pop이 shift와 unshift보다 빠르고 성능이 좋습니다.
shift와 unshift → 맨 앞에서 요소를 변경하므로 기존 배열 요소의 인덱스에 변경이 생깁니다.
push와 pop → 맨 뒤에서 요소를 변경하므로 기존 배열 요소의 인덱스가 변경 없이 유지됩니다.
let arrA = [1, 2];
let arrB = [3, 4];
let arrC = arrA.concat(arrB);
console.log(arrC); // [1, 2, 3, 4]
console.log(arrA); // [1, 2] -> 기존 배열 변화x
arr.slice(start, end); // 배열의 범위 지정하는 두 인수 전달
const arr = [1, 2, 3];
const sliced = arr.slice(0, 2);
console.log(arr); // [1, 2, 3] -> 기존 배열 변화x
console.log(sliced); // [1, 2]
// end 없이 start만 음수 인덱스로 전달시
const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(-1)); // [5]
console.log(arr.slice(-2)); // [4, 5]
console.log(arr.slice(-3)); // [3, 4, 5]
특징
- 순회 메서드
function cb(item, index, array) {
console.log(`${idx}번째 요소: ${item}`);
}
arr.forEach(cb); // 인수로 함수를 요구함 -> 전달한 함수 = 콜백함수
// 함수 표현식, 화살표 함수로 표현 가능
arr.forEach((item, idx) => { console.log(`${idx}번째 요소: ${item}`);});
- 탐색 메서드 : 검색, 카테고리, 필터링 등 여러 상황에 유용
arr.indexOf(item, fromIndex);
// item : 찾으려는 요소 값
// fromIndex : 탐색을 시작할 인덱스 번호 (생략 가능 → 0번째 인덱스부터 탐색)
특징
arr.includes(item, fromIndex);
// indexOf와 사용법이 동일합니다.
function determine(item, idx, arr) {
if (item % 2 === 0) {
return true; // true 반환시 탐색을 끝냄 & 탐색을 멈춘 인덱스 번호 반환
} else {
return false;
}
}
let arr = [1, 3, 5, 6, 8];
let index = arr.findIndex(determine);
// 화살표 함수와 삼항 연산자 이용
let index = arr.findIndex((item) =>
item % 2 === 0 ? true : false
);
특징
let arr = [
{ name: "이종원" },
{ name: "이정환" },
{ name: "신다민" },
{ name: "김효빈" }
];
let element = arr.find((item) => item.name === "이정환");
console.log(element); // {name: "이정환"} -> 요소 반환됨
let arr = [
{ name: "이종원", hobby: "축구" },
{ name: "이정환", hobby: "영화" },
{ name: "신다민", hobby: "축구" },
{ name: "김효빈", hobby: "노래" }
];
let filteredArr = arr.filter(
(item) => item.hobby === "축구"
);
- 변형 메서드 : 배열 변형하거나 요소 재정렬
// arr.map(callback(item, index, array)); 형식
// 배열
let arr = [1, 2, 3, 4];
let newArr = arr.map((item) => item * 3); // 각 요소에 3을 곱한 배열 저장
// 객체
let arr = [
{ name: "이종원", hobby: "축구" },
{ name: "이정환", hobby: "영화" },
{ name: "신다민", hobby: "축구" },
{ name: "김효빈", hobby: "노래" }
];
let newArr = arr.map((item) => item.name); // name프로퍼티만 가진 객체 생성
// arr.sort(compare(a, b)) 형식
let arr = ["b", "a", "c"];
arr.sort(); // 비교함수 생략
console.log(arr); // ["a", "b", "c"]
특징
// 숫자 배열 정렬시
function compare(a, b) {
if (a > b) {
return 1;
} else if (a < b) {
return -1;
} else {
return 0; // 서로 동일하면 자리 변경x
}
} // ( a, b ) 전달 → 양수 : b가 앞에 / 음수 : b가 뒤에 / 0 : 둘의 순서 동일함
let arr = [10, 5, 3];
arr.sort(compare);
// arr.join(separator);
// separator : 각 요소를 구분하는 문자열, 필수x -> 기본값인 콤마로 구분
let arr = ["안녕", "나는", "이정환"];
console.log(arr.join()); // 구분자 생략 -> 안녕,나는,이정환
console.log(arr.join("-")); // 구분자 - 로 지정 -> 안녕-나는-이정환 출력
arr.reduce((acc, item, index, array) => {
(...)
}, initial); // 2개의 인수 전달 → 리듀서(= 콜백함수), 초기값(initial)
//ex
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((acc, item) => acc + item, 0);
console.log(result);
특징
생성
생성자 문법으로 생성하며 인수로 정보 전달 시 생성과 초기화 동시에 진행합니다.
let date = new Date(); // 인수 지정x -> 현재의 날짜와 시간 저장된 객체 반환
시간
한국의 경우 협정 세계시(UTC)의 한국 표준시에 맞춰 1970년 1월 1일 99시 0분 0초를 기준으로 동작하며 UTC+0으로 표현합니다.
let Jan01_1970 = new Date(0);
console.log(Jan01_1970);
// Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)
- 원하는 날짜로 Date 객체 생성
// 문자열로 특정 날짜 전달
let date1 = new Date("2000-10-10/00:00:00");
let date2 = new Date("2000.10.10/00:00:00");
console.log("1:", date1); // 1: Tue Oct 10 2000 00:00:00 GMT+0900 (한국 표준시)
console.log("2:", date2); // 2: Tue Oct 10 2000 00:00:00 GMT+0900 (한국 표준시)
// 숫자로 특정 날짜 전달
let date1 = new Date(2000, 10, 10, 0, 0, 0, 0);
let date2 = new Date(2000, 9, 10); // 0부터 시작하므로 10월 출력하려면 9를 전달
console.log("1:", date1); // 1: Fri Nov 10 2000 00:00:00 GMT+0900
console.log("2:", date2); // 2: Tue Oct 10 2000 00:00:00 GMT+0900
// 타임스탬프로 날짜 생성
let date = new Date(2000, 9, 10);
let timeStamp = date.getTime(); // 저장된 날짜를 타임 스탬프로 변환
console.log(timeStamp); // 971103600000
let dateClone = new Date(timeStamp); // 타임스탬프값을 인수로 전달
console.log(dateClone); // Tue Oct 10 2000 00:00:00 GMT+0900
- 날짜 요소 얻기
- 날짜 요소 수정
- 객체 출력
// 문자열로 반환
console.log(today.toString()); // Tue Oct 10 2000 22:00:00 GMT+0900
// 현재 날짜만 출력
console.log(today.toDateString()); // Tue Oct 10 2000
// 현지화된 날짜와 시간 반환
console.log(today.toLocaleString()); // 2000. 10. 10. 오후 10:00:00 -> 날짜와 시간 모두 반환
console.log(today.toLocaleDateString()); // 2000. 10. 10. -> 날짜만 반환
- 응용
function moveMonth(date, moveMonth) {
const curTimestamp = date.getTime(); // 타임스탬프값 저장
const curMonth = date.getMonth(); // 월 저장
const resDate = new Date(curTimestamp); // Date와 동일한 객체 새로 생성
resDate.setMonth(curMonth + moveMonth); // 기존 월에 이동할 월만큼 더함
return resDate;
} // 이 함수 호출시 moveMonth만큼 월을 앞이나 뒤로 이동
const dateA = new Date("2000-10-10");
console.log("A: ", dateA); // A : Tue Oct 10 2000 09:00:00 GMT+0900
const dateB = moveMonth(dateA, 1);
console.log("B: ", dateB); // B : Fri Nov 10 2000 09:00:00 GMT+0900
const dateC = moveMonth(dateA, -1);
console.log("C: ", dateC); // C : Sun Sep 10 2000 09:00:00 GMT+0900
// pivotDate : 필터링할 월이 있는 Date 객체, dateArray : 코드에서 작성한 Date 객체
function filterThisMonth(pivotDate, dateArray) {
const year = pivotDate.getFullYear();
const month = pivotDate.getMonth();
const startDay = new Date(year, month, 1, 0, 0, 0, 0); // 가장 빠른 시간
const endDay = new Date(year, month + 1, 0, 23, 59, 59); // 가장 늦은 시간
const resArr = dateArray.filter(
(it) =>
startDay.getTime() <= it.getTime() &&
it.getTime() <= endDay.getTime()
); // 시작 날짜와 마지막 날짜안의 객체 요소만 필터링
return resArr;
}
const dateArray = [
new Date("2000-10-1"),
new Date("2000-10-31"),
new Date("2000-11-1"),
new Date("2000-9-30"),
new Date("1900-10-11")
];
const today = new Date("2000-10-10/00:00:00");
const filteredArray = filterThisMonth(today, dateArray);
console.log(filteredArray);
// 0: Sun Oct 01 2000 00:00:00 GMT+0900
// 1: Tue Oct 31 2000 00:00:00 GMT+0900
++ 가장 늦은 시간이 다음 달 0일 23시 59분 59초인 이유
일을 0으로 설정 시 해당 월 바로 이전 월의 마지막 날을 의미함 ( 10월 0일 == 9월의 마지막 날 )
동기
: 위에서부터 아래로 순차적으로 실행하는 것으로 앞의 작업을 완료해야 다음 작업 수행됩니다.
⇒ 작업 흐름 파악은 쉽지만 지연 문제가 생김
비동기
: 앞의 작업과 관계없이 특정 작업을 독립적으로 동작하게 합니다. ( 실행 순서 ≠ 완료 순서 )
setTimeout(() => { ①
console.log("1번!");
}, 3000);
console.log("2번!"); ②
// 2번!
// 1번!
// 1초 기다린 후 전달한 인수에 2 곱해 콘솔에 출력
// setTimeout : JS에 내장된 함수, => 콜백함수 반환값 ≠ setTimeout 반환값
function double(num) {
setTimeout(() => {
const doubleNum = num * 2;
console.log(doubleNum);
}, 1000);
}
double(10);
function double(num, cb) {
setTimeout(() => {
const doubleNum = num * 2;
cb(doubleNum); // 비동기작업 완료시 콜백함수 호출해 결괏값 인수로 전달
}, 1000);
}
double(10, (res) => { // 결괏값 출력을 위함 함수를 인수로 전달
console.log(res);
});
진행 단계 : 3가지 상태로 나뉘어 관리됩니다.
대기 : 작업이 완료되기 전 상태
성공 : 성공적으로 완료 == 해결(rsolve)
실패 : 모종의 이유로 실패 == 거부(reject)
const promise = new Promise(function (resolve, reject) {
setTimeout(() => {
resolve("성공"); // 비동기 작업의 결괏값
}, 500);
});
promise.then(function (res) { // then 메서드 : 작업이 성공했을 때 실행할 콜백 함수 설정
console.log(res);
});
const promise = new Promise(function (resolve, reject) {
setTimeout(() => {
reject("실패");
}, 500);
});
promise.catch(function (err) { // catch 메서드 : 작업이 실패했을 때 실행할 콜백함수 설정
console.log(err);
});
1. 객체를 구조분해할당할 때는 ( key )를 기준으로 합니다.
2. rest 매개변수는 나머지를 모두 배열에 저장하므로 매개변수의 ( 마지막 )에 작성해야 합니다.
3. indexOf는 찾으려는 요소의 ( 인덱스 )를 반환하고 findIndex는 찾으려는 요소의 ( 인덱스 번호 ) 를 반환한다는 차이가 있습니다.
4. sort 메서드는 기본적으로 요소를 ( 문자열 ) 취급하기에 ( 숫자 )로 이루어진 배열을 정렬하려면 비교함수가 필요합니다.
5. ( getTime ) 메서드는 해당 객체에서 시간에 해당하는 타임스탬프를 반환합니다.
6. Date 객체에서 월은 ( 0부터 11 )까지 사이의 숫자로 표현됩니다.
7. ( then ) 메서드와 ( catch ) 메서드를 이용해 작업이 성공하거나 실패했을 때 실행할 콜백 함수를 별도로 설정할 수 있습니다.
코드 작성
1. 아래의 객체 배열에서 취미가 잠자기인 요소만 찾아 새로운 배열로 반환해 콘솔로 출력하는 코드마저 작성하기
let hobbyArr = [
{ name: "덕설", hobby: "뛰어다니기" },
{ name: "덕망", hobby: "잠자기" },
{ name: "미고", hobby: "밥 먹기" },
{ name: "덕조", hobby: "잠자기" }
];
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
let useFilter = hobbyArr.filter(
(item) => item.hobby === "잠자기"
);
console.log(useFilter);
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
2. 1번 문제를 비동기 작업의 상태가 성공일 때만 1초 후에 콘솔에 출력하도록 작성하기 ( 프로미스 객체 이용한 비동기 처리 이용 )
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
const promise = new Promise(function (resolve, reject) {
setTimeout(() => {
resolve(useFilter);
}, 1000);
});
promise.then(function (res) {
console.log(res);
});
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
출처 : 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023)
Corner React.js 1
Editor: ssxb
[React.js 1] p1. 카운터 앱 만들기, 6장. 라이프 사이클과 리액트 개발자 도구 (0) | 2023.11.17 |
---|---|
[React.js 1] 5장. 리액트의 기본 기능 다루기(2) (0) | 2023.11.10 |
[React.js 1] 5장. 리액트의 기본 기능 다루기(1) (0) | 2023.11.03 |
[React.js 1]3장, 4장 Node.js, 리액트 시작하기 (0) | 2023.10.13 |
[React.js 1] 1장. 자바스크립트 기초 (0) | 2023.09.29 |