[사전 스터디 Week 3] JavaScript Object

Gaeun·2022년 9월 20일
0

wecode 사전 스터디

목록 보기
9/14

Object

  • Object(객체)는 자바스크립트 데이터 타입 중 하나이다.
  • 객체는 순서가 없는 데이터 모음이기 때문에 Array(배열)과는 다르게 순서가 중요하지 않다.
  • 객체를 생성할 때는 {} 안에 key와 value를 쌍으로 묶어서 만든다.
  • 객체의 key에는 스페이스, 한글, 특수문자 등이 들어갈 수 있다.
  • key에 스페이스, 특수문자 등이 있을 때에는 따옴표를 사용하지만 $로 시작하는 key는 따옴표가 없어도 된다.
  • key 값이 여러개일 때는 쉼표(,)로 구분한다.
  • value는 모든 유형이 가능하다.
  • key는 property name이라고도 하며, value는 property value라고도 말한다.
const difficult = {
  'my name': 'wecode',
  color: 'black',
  key: 'key는 따옴표가 없어도 됩니다',
  '!key': '!key는 따옴표가 필요합니다',
  $special: '$는 따옴표가 없어도 됩니다'
};

객체 속성에 접근하는 방법

Dot Notation: obj.property - 실제 키 이름을 쓸 때에만 사용 가능
Bracket Notation: obj["property"] - 변수로 접근할 때 사용

공백이 포함되어있거나 숫자로 되어있는 key는 bracket notation을 사용하여야 한다.

console.log(difficult.color);
console.log(difficult['color']);

console.log(difficult.my name); 	// error
console.log(difficult['my name']);

console.log(difficult.33); 			// error
console.log(difficult['33']);

// 변수로 프로퍼티 접근
const name = '키';
console.log(difficult[name]); 	// 접근 가능
console.log(difficult.name);	// undefined

프로퍼티 할당

객체에 이미 key가 존재할 때, 다시 할당하면 값이 교체(수정)된다.
이전에 없었던 key로 접근하여 값을 부여하면 새로운 프로퍼티가 추가된다.

difficult[name] = '값 바꾼다';
console.log(difficult[name]); 			// 값 바꾼다

difficult.color = '색깔';
console.log(difficult.color); 			// 색깔

console.log('생성전: ' + difficult.new); 	// 생성전: undefined
difficult.new = '새로 추가된 프로퍼티';
console.log('생성후: ' + difficult.new); 	// 생성후: 새로 추가된 프로퍼티

const로 선언된 변수는 절대 값을 수정할 수 없다. 하지만 객체에서는 const로 선언한 객체의 프로퍼티를 추가하거나 수정할 수 있다. 이는 객체는 다른 데이터 타입과는 다르게 참조형 데이터이기 때문이다.

객체의 키를 변수로 접근하기

객체의 특정 키 값을 가져오는 것도 가능하지만 반대로 객체에 특정 키를 만들고 값을 할당하는 것도 가능하다.

// 1. information이라는 객체 만들기
const information = {
  name: '김개발'
}

// 2. 키를 생성하고 값을 할당하기
const key = 'job';
const value = 'developer';

// 3. key의 값을 키로 사용, value의 값을 그 키의 값으로 사용한다고 했을 때, 
[A]와 같이 할당 가능.
information[key] = value 		// [A]
information.key = 'developer' 	// [B]

[B]의 방식으로도 할당할 수 있지만 key에 할당된 'job'이라는 값이 프로퍼티명으로 할당되는 것이 아니라 job 자체를 프로퍼티 명으로 할당하게 된다.

console.log(information);

// 출력 결과
{ name: '김개발', job: 'developer' } // [A]
{ name: '김개발', key: 'developer' } // [B]

객체 순회하기

  • 객체는 배열과 다르게 명확하게 정해진 순서가 없기 때문에 객체의 순회는 "순서가 보장되지 않은 순회"이다.
  • cf) 배열 순회 - for문과 length 사용
  • 배열은 length라는 속성을 가지고 있고 인덱스를 통해 각 배열 요소에 접근할 수 있기 때문에 이러한 반복문의 사용이 가능하다. 하지만 객체는 length 속성이 따로 주어져있지 않고 인덱스도 없기 때문에 이러한 식의 반복문은 불가능하다. 하지만 크게 두가지의 방법으로 개체의 반복문 작성이 가능하다.

1. Object.keys()

Object.keys 메서드는 어떤 객체가 가지고 있는 키들의 목록을 배열로 반한하는 메서드이다. 따라서 반환된 해당 배열에 반복문을 사용할 수 있다.

// 키들의 목록을 배열로 반환하기
const obj = {
  name: 'melon',
  weight: 4350,
  price: 16500,
  isFresh: true
}

Object.keys(obj) // ['name', 'weight', 'price', 'isFresh']


// 해당 배열에 반복문 사용하기
const keys = Object.keys(obj)

for (let i = 0; i < keys.length; i++) {
  const key = keys[i] 		// 각각의 키
  const value = obj[key] 	// 각각의 키에 해당하는 값
  
  console.log(value)
}

ES6 문법에서는 Object.values, Object.entries 등이 추가되었다.

Object.values: 객체의 키가 아닌 값으로 이루어진 배열
Object.entries: 객체의 키와 값의 쌍으로 이루어진, length가 2인 배열을 반환. 각 배열에서 인덱스 [0]은 키를, 인덱스 [1]은 해당 키에 해당하는 값을 가진다.

const values = Object.values(obj)	// ['melon', 4350, 16500, true]
const entries = Object.entries(obj)

/*
[
  ['name', 'melon'],
  ['weight', 4350],
  ['price', 16500],
  ['isFresh', true]
]
*/

2. for-in

ES6에서 새로 추가된 for-in은 객체 순회가 가능한 문법이다. 객체 순회 뿐만 아니라 일반적인 배열을 순회할 때에도 사용할 수 있다.

for문 선언시 사용되는 for (let i = 0; i < arr.length; i++) 코드를 for-in문을 통해 간단하게 축약하면 for (let i in arr)로 쓸 수 있다.

객체에 for-in문을 사용하면 인덱스에 해당하는 변수(key)가 숫자가 아닌 객체의 각각의 키에 해당하는 문자열을 할당받게 된다. 아래의 예시에서는 name, weight, price, isFresh를 할당받는다.

const obj = {
  name: 'melon',
  weight: 4350,
  price: 16500,
  isFresh: true
}

for (let key in obj) {
  const value = obj[key]

  console.log('키: ', key)
  console.log('값: ', value)
}

출력되는 결과 값은 아래와 같다.

Assignment

getExamResult 함수 구현하기

scores ::
인자 scores 는 다음과 같은 객체입니다. 객체의 요소의 갯수 및 키의 이름들은 달라질 수 있습니다. 객체의 값은 다음 9가지 알파벳 성적을 의미하는 문자열 중에서 하나를 가지고 있습니다.
A+', 'A', 'B+', 'B', 'C+', 'C', 'D+', 'D', 'F'

// scores 인자 예시
{
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
}

requiredClasses ::
인자 requiredClasses는 다음과 같이 과목명이 문자열로 된 배열입니다.

// requiredClasses 인자 예시
['영어회화', '기초수학', '공학수학', '컴퓨터과학개론']

다음 조건을 만족하는 객체를 반환하도록 함수를 구현해주세요.
1. scores 객체가 가지고 있는 키들은 새로운 객체에 포함되어야 합니다. 단, 그 값들은 다음 원리에 따라 숫자로 바뀌어 할당되어야 합니다. (알파벳 성적 => 숫자 성적)

  • A+ => 4.5
  • A => 4
  • B+ => 3.5
  • B => 3
  • C+ => 2.5
  • C => 2
  • D+ => 1.5
  • D => 1
  • F => 0
  1. requiredClasses 배열의 요소로는 존재하지만, scores의 키로는 존재하지 않는 항목이 있다면, 해당 요소는 새로운 객체의 키가 되고, 값으로 0을 가져야 합니다. 요소간 순서는 다를수 있지만, 이는 채점에 무관합니다.
// 앞서 언급된 예시를 인자로 받은 함수가 반환하는 객체
{
  '생활속의회계': 2,
  '논리적글쓰기': 3,
  '독일문화의이해': 3.5,
  '기초수학': 1.5,
  '영어회화': 2.5,
  '인지발달심리학': 4.5,
  '공학수학': 0,
  '컴퓨터과학개론': 0,
}

이 문제를 몇 번을 읽어봤는지 모르겠다. 읽으면 읽을수록 쉬울 것 같으면서도 너무나도 어려워보여서 과제에서 원하는 것을 아래와 같이 내 방식대로 정리했다.

  • scores 인자 중 하나를 예로 들어 '생활속의회계': 'C' 를 ''생활속의회계': 2'로 반환하기
  • requiredClasses 인자 중 하나를 예로 들어 scores에 없는 인자인 '공학수학'을 ''공학수학': 0' 로 반환하기

코드는 이런 방식으로 작성해보았다.

const convertExamResult = (scores, requiredClasses) => {

// 1. 우선 결과가 출력될 빈 objcet를 선언
  const result = {};

// 2. `scores` 객체를 배열로 만들고 알파벳 성적을 숫자 성적으로 바꾸기
  let letterToNum = {
  'A+': 4.5,
  'A': 4,
  'B+': 3.5,
  'B': 3,
  'C+': 2.5,
  'C': 2,
  'D+': 1.5,
  'D': 1,
  'F': 0
  }

  for (let i in scores) {
    result[i] = letterToNum[scores[i]];
  }

// 3.`requiredClasses` 배열의 요소로는 존재하지만, `scores`의 키로는 존재하지 않는 항목을 새로운 키로 추가, 값을 0으로 할당

   const keys = Object.keys(result)
  
    for (let i in requiredClasses) {
      if (!keys.includes(requiredClasses[i])) {
  	      result[requiredClasses[i]] = 0
      }
    }
    
// 4. 결과를 반환할 return을 작성한다.
  return result
}

2번도 굉장히 오랜 시간이 걸려 작성하였지만 3번에서 더 오랜 시간 작성하였다. 처음 작성했던 코드는 구글링으로 알게 된 .hasOwnProperty()를 사용하였으나 자꾸 에러가 떠서 10분간 고민하다 원래 알고 있던 .includes()를 사용하였다. 왜 문제를 풀 때엔 알고 있던 메서드가 바로 생각이 안 나는 건지...

if문을 간결하게 쓰고 싶어 이런저런 시도를 해보았다.
requiredClasses[i]가 key로 존재하지 않는다면을 if (!keys.includes(requiredClasses[i])) 로 작성하였다. 거기까진 좋았으나... result[requiredClasses[i]]라고 적어야하는 것을 result[i]라고 적어 한참을 씨름하고 있었다.

⭐️ 가장 어려웠던 부분들을 하나씩 뜯어서 이해해보자면,

  • result[i] = letterToNum[scores[i]]:
    • [i]에는 scores 객체의 key가 순환되며 저장된다.
    • ex) reuslt[생활속의회계] = letterToNum[scores[생활속의회계]]`
    • 위에서 살펴본 Bracket Notation을 토대로 scores[생활속의회계] = 'C'
    • letterToNum[C] = 2
    • result[생활속의회계] = 2
  • result[requiredClasses[i]] = 0: result라는 객체에 requiredClasses 배열의 i번째 인덱스를 키로 하는 값을 0으로 할당한다.

22/11/16 추가
다시 풀어보아도 너무 까다로운 이 문제...
이번엔 그래도 덜 고민하며 풀었다!

const convertExamResult = (scores, requiredClasses) => {
  // 영어 성적 -> 숫자 성적
  const grade = { "A+": 4.5, "A": 4, "B+": 3.5, "B": 3, "C+": 2.5, "C": 2, "D+": 1.5, "D": 1, "F": 0 }
  
  // scores value값은 숫자 성적으로 변경
  for (let key in scores) {
    scores[key] = grade[scores[key]]
  }
  
  // scores 객체 내에 없는 requiredClasses는 0으로 변경
  const key = Object.keys(scores)
  
  for (let i in requiredClasses) {
    if (!key.includes(requiredClasses[i])) {
      scores[requiredClasses[i]] = 0
    }
  }
  return scores;
  
}
  1. 귀차니즘인 건지... 평소였으면 결과를 반환할 새 객체를 만들었을텐데 이번엔 그냥 scores에 덮어 씌우기를 했다...😂
  2. grade라는 객체를 만들어서 키에는 영어 성적, 값에는 숫자 성적을 할당했다.
  3. Object.keys 메서드를 활용하여 key만 담긴 배열을 만들었고
  4. 그 배열을 순회하면서 requiredClasses 배열과 비교하며 값을 할당했다.
  5. 그리고 다시 scores 반환!

이 문제를 처음 풀었을 때에는 문제 자체도 몇 번을 읽어보았고, 코드를 작성하는데도 자꾸 고민하고, 콘솔에 하나 하나 다 찍어가며 했었는데 오랜만에 다시 푸니 술술 적어내려갔다. 성장하고 있다는 것을 새삼 느낀 하루! 내가 해냄!

profile
🌱 새싹 개발자의 고군분투 코딩 일기

0개의 댓글