Programming/Frontend

(React) 기초 - 객체와 배열

armyost 2024. 10. 31. 22:06
728x90

객체와 배열

ES2016부터 객체와 배열을 다루는 방법과 객체와 배열안에서 변수의 영역을 제한하는 방법을 다양하게 제공하기 시작했다. 이런 기능으로는 구조 분해, 객체 리터럴 개선, 스프레드 연산자 등이 있다. 

 

구조 분해를 사용한 대입

구조 분해를 사용하면 객체 안에 있는 필드 값을 원하는 변수에 대입할 수 있다. 다음 sandwich 객체를 생각해보자, sandwich에는 4개의 필드가 있다. 하지만 그중에서 bread와 meat 필드의 값이 필요하다. 

const sandwich = {
	bread: "더치 크런치",
    meat: "참치",
    cheese: "스위스",
    toppings: ["상추","토마토","머스타드"]
};

const {bread, meat} = sandwich;
console.log(bread, meat); // 더치 크런치 참치


let {bread, meat} = sandwich;

bread = "마늘";
meat = "칠면조";

console.log(bread); // 마늘
console.log(meat); // 칠면조

console.log(sandwich.bread, sandwich.meat); // 더치 크런치 참치

 

객체의 필드에 접근하기 위해 점(.)과 필드 이름을 사용하는 대신, regularPerson에서 필요한 값을 구조 분해로 가져올 수도 있다.

const lordify = ({firstname}) => {
	console.log('캔터베리의 ${firstname}')
};

const regularPerson = {
	firstname: "현석",
    lastname: "오"
};

lordify(regularPerson); // 캔터베리의 현석

 

데이터를 변경하고 이에 맞춰 한 수준 더 깊이 들어가보자. 이제는 regularPerson 객체 안에 spouse를 키로 하는 새로운 객체를 포함시킨다. 

const regularPerson = {
	firstname: "현석",
    lastname: "오",
    spouse: {
    	firstname: "계영",
        lastname: "이"
    }
};

 

배우자의 이름도 캔터베리의 영주로 만들고 싶다. 함수에 있는 구조 분해 인수를 약간만 조정해주면 된다. 

const lordify = {{ spouse: {firstname} }} => {
	console.log('켄터베리의 ${firstname}');
};
lordify(regularPerson); // 캔터베리의 계영

 

콜론과 내포된 중괄호를 사용해 firstname을 spouse  객체로부터 구조 분해할 수 있다. 

 

배열 구조 분해하기

배열을 구조 분해해서 값을 뽑아낼 수도 있다. 배열의 첫번째 원소를 변수에 대입하고 싶다고 가정하자. 

const [firstAnimal] = ["캥거루", "월뱃", "코알라"];
console.log(firstAnimal); // 캥거루

불필요한 값을 콤마를(,)를 사용해 생략하는 리스크 매칭을 사용할 수 도 있다. 변수에 대입하지 않고 무시하고 싶은 원소의 위치에 콤마를 넣으면 리스트 매칭을 사용하는 것이다. 앞에서 본 것과 같은 배열에서 최초의 두 원소를 콤마로 대치하면 다음과 같다. 

 

const [,,thirdAnimal] = ["캥거루","월벳","코알라"];
console.log(thirdAnimal); // 코알라

 

객체 리터럴 개선

객체 리터럴 개선은 구조 분해의 반대라 할 수 있다. 객체 리터럴 개선은 구조를 다시 만들어내는 과정 또는 내용을 한데 묶는 과정이라 할 수 있다. 객체 리터럴 개선을 사용하면 현재 영역에 있는 변수를 객체의 필드로 묶을 수 있다. 

const name = "탈락";
const elevation = 9738;

const funHike = {name, elevation};
console.log(funHike); // {name:"탈락", elevation: 9738}

 

이제 funHike 객체에는 name과 elevation 이라는 필드가 들어가 있다. 

객체 리터럴 개선 또는 객체 재구축을 통해 객체 메서드를 만드는 것도 가능하다. 

const name = "탈락";
const elevation = 9738;
const print = function() {
	console.log('$(this.name) 산의 높이는 ${this.elevation} 피트입니다.')
};

const funHike = {name,elevation,print};

funHike.print(); // 탈락 산의 높이는 9738 피트입니다.

 

객체 메서드를 정의할 때는 더이상 function 키워드를 사용하지 않아도 된다.

// 옛날 방식
var skier = {
	name: name,
    sound: sound,
    powderYell: function() {
    	var yell = this.sound.toUpperCase();
        console.log('${yell} ${yell} ${yell}!!!');
    },
    speed: function(mph) {
    	this.speed = mph;
        console.log('속력(mph):',mph);
    }
}

// 새로운 방식
const skier = {
	name,
    sound,
    powderYell() {
    	let yell = this.sound.toUpperCase();
        console.log('${yell} ${yell} ${yell}!!!');
    },
    speed(mph) {
    	this.speed = mph;
        console.log('속력(mph):', mph);
    }
}

객체 리터럴 개선을 통해 현재 영역에서 볼수 있는 변수들을 객체의 필드에 대입할 수 있으며, function 키워드를 입력하지 않아도 되기 때문에 타이핑 해야 할 양이 줄어든다.

 

스프레드 연산자

스프레드 연산자는 3개의 점으로 이뤄진 연산자로 몇가지 다른 역할을 담당한다. 첫째로 스프레드 연산자를 사용해 배열의 내용을 조합할 수 있다. 예를 들어 두 배열이 있다면, 두 배열의 모든 원소가 들어간 세번째 배열을 만들 수 있다. 

const peaks = ["대청봉","중청봉","소청봉"];
const canyons = ["천불동계곡","가야동계곡"];
const seoraksan = [...peaks, ...canyons];

console.log(seoraksan.join(', ')); // 대청봉, 중청봉, 소청봉, 천불동계곡, 가야동계곡

peaks와 canyons에 포함된 모든 원소가 seoraksan이라는 새 배열에 들어간다.

 

이제 스프레드 연산자가 해결해주는 문제를 한 가지 살펴보자. 앞의 예제에서 정의한 peaks 배열에서 마지막 원소를 변수에 담고 싶다. Array.reverse 메서드를 사용해 배열을 뒤집고 구조 분해를 사용해 첫번째 원소를 변수에 넣으면 될 것 같다. 

const peaks = ["대청봉", "중청봉", "소청봉"];
const [last] = peaks.reverse();

console.log(last); 	// 소청봉
console.log(peaks.join(', '));	// 소청봉, 중청봉, 대청봉

 

문제점을 알 수 있는가? 실제로 reverse 메서드는 원래의 배열을 변경한다. 하지만 스프레드 연상을 사용하면 원본 배열을 뒤집지 않고 복사본을 만들어서 뒤집을 수 있다. 

const peaks = ["대청봉","중청봉","소청봉"];
const [last] = [...peaks].reverse();

console.log(last);				// 소청봉
console.log(peaks.join(', ')); // 대청봉, 중청봉, 소청봉

스프레드 연산자를 사용해 배열의 원소들을 복사했기 때문에, 원본인 peaks는 변경되지 않고 그대로 남게 된다. 따라서 나중에 필요할때 다시 사용할 수 있다. 

 

또한 스프레드 연산자를 통해 배열의 나머지 원소들을 얻을 수도 있다.

const lakes = ["경포호","화진포","송지호","청초호"];
const [first, ...rest] = lakes;

console.log(rest.join(", ")); // "화진포, 송지호, 청초호"

 

세 점 구문을 사용해 함수의 인자를 배열로 모을 수도 있다. 이런 식으로 함수 파라미터 정의에서 스프레드 연산자가 쓰일때는 레스트 파라미터라고 부른다. 다음 예제에서는 n개의 인자를 스프레드 연산자를 사용해 배열로 모은 다음에, 그 배열을 사용해 여러가지 내용을 콘솔 메시지로 찍는 함수를 보여준다. 

function directions(...args) {
	let [start, ...remaining] = args;
	let [finish, ...stops] = remaining.reverse();
    
    console.log('${args.length} 도시를 운행합니다.');
    console.log('${start} 에서 출발합니다.');
}

directions(
	"서울",
	"수원",
	"천안",
	"대전",
	"대구",
	"부산"
);

direction 함수는 스프레드 연산자를 사용해 인자를 받는다. 첫번째 인자는 start 변수에 대입된다. 마지막 인자는 finish 변수에 Array.reverse를 통해 대입된다. 그 후 args 배열의 length를 사용해서 얼마나 많은 도시를 지나는지를 보여준다. 

 

스프레드 연산자를 객체에도 사용할 수 있다. 

const morning = {
	breakfast: "미역국",
    lunch: "삼치구이와 보리밥"
};

const dinner = "스테이크 정식";

const backpackingMeals = {
	...morning,
    dinner
};

console.log(backpackingMeals); // {breakfast: "미역국", lunch: "삼치구이와 보리밥", dinner: "스테이크 정식"}