2024/04/02 객체 심화

YIS·2024년 4월 2일
post-thumbnail

객체 순회

Object.keys, values, entries

객체와 관련된 데이터를 다룰 때 유용하게 쓰는 메서드.
이 메서드들은 객체의 데이터를 배열 형태로 반환하여,
객체의 데이터를 순회하거나 다루기 쉽게 해줌.

  • Object.keys(obj) : 객체의 모든 키를 문자열 배열로 반환.
  • Object.values(obj) : 객체의 모든 값을 배열로 반환.
  • Object.entries(obj) : 객체의 모든 키-값 쌍을 배열의 형태로 반환.
    각 키-값은 또 다른 배열로 표현됨.
const person = { name: "홍길동", age: 25, city: "서울" };

console.log(Object.keys(person)); // ["name", "age", "city"]
console.log(Object.values(person)); // ["홍길동", 25, "서울"]
console.log(Object.entries(person)); // [["name", "홍길동"], ["age", 25], ["city", "서울"]]

자바스크립트에서는 다양한 자료 구조를 다루며, 이들을 순회하기 위해 특정 메서드들이 제공됨. Object.keys, Object.values, Object.entries는 일반 객체에 적용되는 메서드들로,
객체의 키, 값, 키-값 쌍을 배열로 반환.
이와 비교해, Map, Set, Array와 같은 내장 자료 구조에는 자체적인
.keys(), .values(), .entries() 메서드가 존재.

각 전용 메서드와 일반객체 메서드의 차이점은 다음과 같다.
이해안되지만 일단 정의하고 넘어감

  • 호출방식
    Map,Set,Array는 .keys(), .values(), .entries()와 같은 인스턴스 메서드를 직접 호출함. 예를 들어, map.keys()는 맵 객체 내의 모든 키를 순회할 수 있는 이터러블 객체를 반환함.
    일반 객체는 Object.keys(obj), Object.values(obj), Object.entries(obj)와 같이 Object 전역 객체를 통해 메서드를 호출해야됨. obj.keys() 이런식은 안됨.

    사용자가 일반객체에 values()와 같은 메서드를 직접 정의하고 사용할수있기때문에
    사용자가 정의한 메서드와 내장 메서드간의 충돌발생가능성도 있음. 그래서
    Object.values(obj)와 같은 형태로 호출하면 서로 구분하여 사용할수 있기 때문에 더 유연함.

  • 반환 값의 차이
    Map은 키와 값을 연결하는 구조임. 맵에서 제공하는 메서드 (예: .keys(), .values(), .entries())를
    사용하면 이터러블 객체를 받게 됨.
    '이터러블 객체'란, 반복해서 하나씩 꺼내 볼 수 있는 '목록'과 같은 것. for..of 같은
    반복문을 사용하여 이터러블 객체의 내용물을 하나씩 순회 할 수 있음.

    일반객체는 진짜 배열을 받게 됨.
    그래서 배열의 모든 기능 (.map(), .filter(), .reduce() 등)을 사용할 수 있음.

심볼형 프로퍼티는 객체의 고유한 키로 사용될 수 있는 심볼(symbol) 값을 말함.
Object.keys, Object.values, Object.entries는 심볼형 프로퍼티를 무시하고,
오직 문자열 키에 대해서만 작업함.
심볼형 키를 포함한 객체의 키를 다루고 싶다면,
Object.getOwnPropertySymbols 또는 Reflect.ownKeys(obj) 메서드를 사용해야 함.




객채 변환하기

객체엔 map, filter 같은 배열 전용 메서드를 사용할 수 없음.
Object.entries와 Object.fromEntries를 순차적으로 적용하면
객체에도 배열 전용 메서드 사용할 수 있음

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};
let doublePrices = Object.fromEntries(
   Object.entries(prices).map(([key, value]) => [key, value * 2])
);
console.log(doublePrices.meat); // 8

Object.entries(prices)를 사용해 객체의 키-값을 배열로 받음. 여기에 map 배열전용메서드를 사용,
값으로 받은 value를 *2해줌 그리고 다시 Object.fromEntries() 를 사용해 배열을 객채로 돌림.

그런데 나는 공부 하면서 느끼는거지만 (초보자, 입문자 입장)
코드 진행순서가 위에서부터 아래로 자연스럽게 오는게 눈에 잘들어옴.
꼭 비단 이것뿐만이 아니라, 다른 예시에서도
아마 익숙해지게 되면서부터는 간결함을 추구하게 되니깐이러지 않을까? 라는생각은 함.
어쨌든 내기준에서

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};
let entries = Object.entries(prices);
let doubledEntries = entries.map(([key, value]) => [key, value * 2]);
let doublePrices = Object.fromEntries(doubledEntries);

console.log(doublePrices.meat); // 8

이런느낌? 위에서부터 차례대로 한줄씩 해주면 눈에는 일단 잘들어와서 좋긴함.
entries로 배열로 바꿔주고 >> 그값을 map으로 변경해주고 >> 그걸 다시 fromEntries로 객채로변환.
물론 이러면 쓰잘대기없는 변수들이 많이 나오긴함. 이것도 권장되는건 아님
아직 잘 모르겠음. 한번에 딱보고 감이 오면 좋은데 머리가 나빠서.




구조 분해 할당

배열이나 객체의 속성을 분해하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript의 표현식
배열이나 객체로부터 데이터를 쉽게 추출할 수 있음.
어떤 것을 복사한 이후에 변수로 분해(destructurize)해준다.
이 과정에서 분해 대상은 수정 또는 파괴되지 않음

배열 분해하기

기본문법
let [변수1, 변수2, ...] = 배열;

  • 배열 구조 분해 : 배열 요소를 개별 변수에 할당할 수 있음.
let arr = ["Bora", "Lee"]
let [firstName, surname] = arr;

console.log(firstName); // Bora
console.log(surname);  // Lee
  • 배열뿐만 아니라 모든 이터러블(iterable, 반복 가능한 객체)에 구조 분해 할당을 적용할 수 있음.
let [a, b, c] = "abc"; // ["a", "b", "c"]
let [one, two, three] = new Set([1, 2, 3]); //이건 아직 모르겠음 Set모름
  • 할당 연산자 좌측엔 ‘할당할 수 있는(assignables)’ 것이라면 어떤것이든 가능.
    아래와 같이 객체 프로퍼티도 가능.
let user = {};
[user.name, user.surname] = "Bora Lee".split(' ');
console.log(user.name); // Bora
  • Object.entries(obj)와 구조 분해를 조합하면 객체의 키와 값을 순회해 변수로 분해 할당할수 있음.
let user = {
  name: "John",
  age: 30
};

for (let [key, value] of Object.entries(user)) {
  //객체를 배열로 바꿈[[name,John],[age,30]] 각각 key, value변수로 들어감
  console.log(`${key}:${value}`); // name:John, age:30이 차례대로 출력
}
  • 맵에도 물론 이 메서드를 활용할 수 있음.(이 부분은 잘모름. 일단 정의)
let user = new Map();
user.set("name", "John");
user.set("age", "30");

for (let [key, value] of user) {
  alert(`${key}:${value}`); // name:John, then age:30
}
  • 두 변수에 저장된 값을 교환할 때 구조 분해 할당을 사용할 수 있음.
let guest = "Jane";
let admin = "Pete";

[guest, admin] = [admin, guest];// 이미 저장된 변수값에 값을 새로 넣어줌

console.log(`${guest} ${admin}`); // guest: Pete, admin: Jane
  • 쉼표를 사용하여 요소 무시하기 : 필요 없는 요소는 쉼표를 사용해 건너뛸 수 있음.
let [firstName,,title] = ["Julius", "Caesar", "Consul"];
//두 번째 요소는 생략되고, 세 번째 요소가 title이라는 변수에 할당됨.
console.log(title); // Consul
  • '…'로 나머지 요소 가져오기 : 앞쪽의 몇 개의 요소를 제외한 나머지 모든 요소를
    새로운 배열로 가져올 수 있음.
let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

console.log(name1); // Julius
console.log(name2); // Caesar

// `rest`는 배열.
console.log(rest[0]); // Consul
console.log(rest[1]); // of the Roman Republic
console.log(rest.length); // 2
  • 기본값 : '='을 이용하면 할당할 값이 없을 때 기본으로 할당해 줄 값인
    '기본값(default value)'을 설정할 수 있음.
let [name = "Guest", surname = "Anonymous"] = ["Julius"];

console.log(name);    // Julius (배열에서 받아온 값)
console.log(surname); // Anonymous (기본값)

객체 분해하기

기본문법
let { 속성1, 속성2, ...} = 객체;
속성1, 속성2는 객체 내의 키 이름과 동일해야 하며, 해당 키에 해당하는 값이 변수에 할당됨.

let options = {
  title: "Menu",
  width: 100,
  height: 200
};
let {height, width, title} = options;
//프로퍼티 순서는 상관없음. {title, width, height},{width, height, title} 똑같음.

console.log(title);  // Menu
console.log(width);  // 100
console.log(height); // 200
  • 객체 프로퍼티를 프로퍼티 키와 다른 이름을 가진 변수에 저장할수 있음.
    좌측 패턴에 콜론(:)을 사용하면 됨
let options = {
  title: "Menu",
  width: 100,
  height: 200
};
let {width: w, height: h, title} = options; // { 객체 프로퍼티: 목표 변수 }
// width -> w 
// height -> h
// title -> title
//프로퍼티 width를 변수 w에, 프로퍼티 height를 변수 h에 저장

console.log(title);  // Menu
console.log(w);  // 100
console.log(h); // 200
  • 배열과 마찬가지로 기본값 설정 가능함
let options = {
  title: "Menu"
};
let {width = prompt("width?"), title = prompt("title?")} = options;

console.log(title);  // Menu
console.log(width);  // prompt 창에 입력한 값
  • 콜론(:)과 할당 연산자 동시에 사용 가능. 당연하지만 원본객체에 값이 없는경우만 기본값설정가능
let options = {
  title: "Menu"
};
let {width: w = 100, height: h = 200, title} = options;

console.log(title);  // Menu
console.log(w);      // 100
console.log(h);      // 200
  • '...'나머지 패턴
let options = {
  title: "Menu",
  height: 200,
  width: 100
};
let {title, ...rest} = options;
// title = 이름이 title인 프로퍼티
// rest = 나머지 프로퍼티들

// title엔 "Menu", rest엔 {height: 200, width: 100}이 할당.
console.log(title);  // 200
console.log(rest.height);  // 200
console.log(rest.width);   // 100
  • let 없이 사용하기
    let으로 새로운 변수를 선언하지 않고 기존에 있던 변수에 분해한 값을 할당할 수도 있음
let title, width, height;
({title, width, height} = {title: "Menu", width: 200, height: 100});
//구조분해할당을 단독으로 사용할 때는 괄호()로 식을 감싸줘야됨. 
//{}가 블록 구문으로 해석될 수 있기 때문에, 괄호로 감싸주어 구조 분해 할당임을 명시 
console.log(title); // Menu
console.log(width); // 200
console.log(height); // 100

중첩 구조 분해

객체나 배열이 다른 객체나 배열을 포함하는 경우, 복잡한 데이터 구조를 간결하게 분해하여
그 내부의 값을 변수에 쉽게 할당할 수 있게 해주는 문법

let options = {
  size: {
    width: 100,
    height: 200
  },
  items: ["Cake", "Donut"],
  extra: true
};

let {
  size: {
    width,
    height
  }, // size는 여기,
  items: [item1, item2], // items는 여기에 할당함
  title = "Menu" // 분해하려는 객체에 title 프로퍼티가 없으므로 기본값을 사용함
} = options;

console.log(title);  // Menu
console.log(width);  // 100
console.log(height); // 200
console.log(item1);  // Cake
console.log(item2);  // Donut



똑똑한 함수 매개변수

구조 분해 할당을 사용한 함수 매개변수

구조 분해 할당을 활용하면 함수의 매개변수를 객체의 형태로 전달하고,
함수 내부에서 필요한 프로퍼티를 쉽게 추출할 수 있음.
이 방법을 사용하면 매개변수의 순서를 신경 쓸 필요가 없고,
선택적 매개변수를 다루기도 용이함

// 함수에 전달할 객체
let options = {
  title: "My menu",
  items: ["Item1", "Item2"],
  width: 300
};
// 똑똑한 함수는 전달받은 객체를 분해해 변수에 즉시 할당함
function showMenu({title = "Untitled", width = 200, height = 100, items = []}) {
  // title, items , width – 객체 options에서 가져옴
  // height – 기본값
  console.log( `${title} ${width} ${height}` ); // My Menu 300 100
  console.log( items ); // Item1, Item2
}
showMenu(options);

중첩 객체와 콜론을 사용한 복잡한 구조 분해

구조 분해 할당은 중첩된 객체와 배열에도 사용할 수 있으며,
변수 이름을 변경하고 싶을 때 콜론(:)을 활용

let options = {
  title: "My menu",
  items: ["Item11", "Item22"],
};
function showMenu({
  title = "Untitled",
  width: w = 100,  // width는 w에 할당됨
  height: h = 200, // height는 h에 할당됨
  items: [item1, item2] // items의 첫 번째 요소는 item1에, 두 번째 요소는 item2에 할당함
}) {
  console.log( `${title} ${w} ${h}` ); // My Menu 100 200
  console.log( item1 ); // Item11
  console.log( item2 ); // Item22
}
showMenu(options);

함수 매개변수를 구조 분해할 때는 인수가 전달되었다고 가정함.
인수를 전혀 전달하지 않는 경우를 처리하기 위해서는
전체 매개변수 객체에 기본값으로 빈 객체 {}를 설정해야 함.

function showMenu({title = "Menu", width = 100, height = 200} = {}) {
  console.log( `${title} ${width} ${height}` );
}
showMenu(); // 에러 없이 'Menu 100 200' 출력
profile
엉덩이가 무거운 사람

0개의 댓글