5-객체
코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.
구문
목차
1-개념
1-1-정의
0개 이상의 프로퍼티(property:속성) 의 집합.
화살표함수에서는 함수의 렉시컬 스코프를 가르킴"
const person = {
name: 'Kim', // 프로퍼티
age: 30, // 프로퍼티
~~ greet: function () { // 메서드
return `Hello, I'm ${this.name}`;
}
~~greet() { // 메서드
return `Hello, I'm ${this.name}`;
}
};
프로퍼티는 키(key)와 값(value)으로 구성됨.
- 프로퍼티: 객체의 상태를 나타내는 값
- 메서드: 프로퍼티를 참조하고 조작할수 있는 동작
2-객체의 생성
2-1-객체리터럴 \{ \}
const person = {
name: "Kim",
age: 25,
greet () {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet();
2-2-Object 생성자함수 new Object()
const person = new Object();
person.name = "Kim";
person.age = 25;
person.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
person.greet();
2-3-생성자함수
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
}
const person1 = new Person("Kim", 25);
person1.greet();
2-4-Object.create메서드
const personPrototype = {
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const person = Object.create(personPrototype);
person.name = "Kim";
person.age = 25;
person.greet();
2-5-클래스
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person("Kim", 25);
person.greet();
3-프로퍼티
3-1-요소
객체는 프로퍼티의 집합이며 프로퍼티는 키와 값으로 구성된다.
const person = {
//키는 name, 값은 kim
name: "Kim",
age: 25,
};
프로퍼티의 키는 프로퍼티 값의 구별을 위한 식별자의 역할을 한다. 키의 생성시 자바스크립트 식별자의 규칙을 따르지 않아도 되나 그럴경우 “”로 묶어서 표기해야 한다.
const person = {
"01": "Kim",
"나이": 25,
"e-mail": "qwer@qu.com"
};
이렇게 선언한 프로퍼티는 대괄호를 사용하여 접근할수 있다. 점 표기법으로 접근시 뺄셈연산자로 인식하게 되는 문제가 발생하므로 유의해야 한다.
console.log(person['e-mail']);
키는 아래와 같이 숫자와 예약어를 지정할수 있다
const property = {
0: 1,
function: function(){
console.log('fun');
}
}

숫자로 지정한 키는 암묵적으로 자료형이 문자형으로 변환된 것이 확인된다.
3-2-접근
const dot = {
name: 'me'
}
console.log(dot.me);
console.log(dot['me']);
위의 경우 처럼 존재 하지 않는 키에 접근해도 참조오류가 아닌 undefined 가 반환되는 점에 유의해야 한다.
프로퍼티는 두가지 방법으로 접근할수 있다.
**3-2-1-****. **마침표 표기법(dot notation)
const dot = {
name: 'me'
}
console.log(dot.name);
**3-2-2-[] **대괄호 표기법(bracket notation)
const dot = {
name: 'me'
}
console.log(dot['name']);
프로퍼티의 키가 숫자인 경우는 대괄호 접근시 따옴표를 생략할수 있다.
3-3-갱신
const dot = {
name: 'me',
}
dot.name='you'
console.log(dot.name);
이미 존재하는 프로퍼티에 값을 재할당 하면 값이 갱신된다.
3-4-동적생성
dot.age = 20;
console.log(dot);
dot.gender="female";
console.log(dot)
dot 객체에는 age 프로퍼티가 추가되고 값이 할당되었다.
3-5-삭제
const person = {
name: 'Kim'
}
person.age = 10;
delete person.age;
delete person.address;
person 객체는 name 프로퍼티가 있다. age를 동적으로 생성후 delete 키워드로 삭제한다. 이후 존재하지 않는 address 키 삭제시 오류가 안나는 것을 확인해본다
4-객체리터럴의 확장기능
4-1-프로퍼티 축약
const x = 1, y = 2;
//const obj = { x: x, y: y }
const obj = { x, y }
console.log(obj);
4-2-계산된 프로퍼티명
문자열이나 문자열로 평가되는 표현식을 사용하여 프로퍼티 키를 동적생성할수 있다.
이때 [] 를 사용해야 한다.
const prefix = 'prop'
let i = 0;
const obj = {}
obj[prefix + '-' + ++i] = i
obj[`${prefix}-${++i}`] = i
console.log(obj)

{
const prefix = 'prop';
let i = 0;
const obj = {
[`${prefix}-${++i}`]: i,
[`${prefix}-${++i}`]: i,
[`${prefix}-${++i}`]: i,
}
console.log(obj);
4-3-메서드 축약
프로퍼티 값으로 함수를 할당
{
//1
const obj = {
name: "kim",
say: function () {
console.log('hi' + this.name);
}
}
obj.say();
}
{
//2
const obj = {
name: "kim",
say () {
console.log('hi' + this.name);
}
}
obj.say();
}
1의 메서드를 2로 축약할수 있다.
5-객체의 순회
5-1-for~in
5-2-Object.key()
5-3-Object.entries()
5-4-Object.values()
6-객체의 병합과복사
Info: 얕은복사→깊은복사
깊은복사↛얕은복사 자바스크립트의 7가지 자료형은 크게 원시타입(primitive type)과 객체타입(object/reference type)으로 나눌수 있다. 자료형의 구분표를 참조하자.
- **원시 타입(Primitive Type)**은 값이 변경 불가능(immutable) 하며, 변수에 직접 저장된다.
- **객체 타입(Object Type)**은 값이 변경 가능(mutable) 하며, 메모리 주소(참조)로 저장된다..
//const 키워드를 사용한 변수는 값의 재할당 불가
const o = {}
//그러나 객체는 변경할수 있다.
o.a = 1
console.log(o);
6-1-문자열과 불변성
문자열은 다른 원시타입과 다른 특징이 있다. 문자열이란 0개 이상의 문자로 이루어진 집합을 의미하고 1개의 문자는 대략 2byte의 메모리공간에 저장된다. 숫자의 경우 1도 10000000도 같은 8byte의 공간을 차지한다. 그러나 문자열은 대략 “1”은 2byte “10”은 4byte 가 필요하다.
var str = "hello";
str = "world"


str 이라는 식별자에 값이 재할당 되는것이 아니라 값이 저장되는 메모리가 생성되고 식별자가 가르키는 메모리주소가 바뀐다.
문자열은 유사배열객체로 취급되어 배열과 유사하게 각 문자에 접근할수 있다.
console.log(str[1]);
그러나 원시타입이므로 값은 불변성을 유지하기 때문에 아래의 코드는 값이 재할당 되지 않는다
str[1] = "a"
console.log(str[1]);
6-2-복사(Copy)
6-2-1-참조(Reference)
- 아래와 같은 형태의 중첩된 값을 살펴보자.
const y = [1, 2, 3, [11, 12, 13]];
- 변수_y 에 y를 복사하고 출력한다
const _y = y;
console.log(`원본:${y}//${y === _y} `);
console.log(`복사_y:${_y}`);

- 데이터를 바꾸고 출력값을 확인한다.
_y[0] = 5;
_y[3][0] = 105;
console.log(`원본:${y}//${y === _y} `);
console.log(`복사_y:${_y}`);

_y 의 값을 변경 하였는데 원본데이터도 바뀌었다. 참조에 의한 전달은 완전히 동일한 메모리 주소를 공유하므로 **한쪽을 수정하면 다른 쪽도 즉시 변경된다 **
6-2-2-얕은복사(Shallow Copy)
- 변수 __y 에 y를 얕은복사로 할당해보자
const __y = [...y];
console.log(`원본:${y}//${y === __y} `);
console.log(`복사...y:${__y}`);

- 데이터를 변경해보자
__y[0] = "😘";
__y[3][0] = "abc";
console.log(`원본:${y}//${y === __y} `);
console.log(`복사...y:${__y}`);

얕은 복사는** 최상위 레벨의 속성을 새로운 메모리 공간에 복사하므로 값이 변경되지 않는다. 그러나 중첩된 객체의 수정시 원본도 바뀐다**.
얕은복사 방법
- 스프레드 연산자 (
\{ ...original \}) Object.assign(\{\}, original)Array.from()slice()(배열의 경우)
6-2-3-깊은복사(Deep Copy)
- 변수 deepY 에 y를 깊은복사 해보자
const deepY = JSON.parse(JSON.stringify(y));
console.log(`원본:${y}`);
console.log(`deepY:${deepY}`);

- 값을 바꿔보자
deepY[0] = '12';
deepY[3][0] = 12;

깊은복사는 중첩데이터까지 새로운 메모리 공간에 저장하므로 완전한** 데이터 독립성이 보장**된다.
깊은복사방법
npm i lodash
const _ = require('lodash');
const c2 = _.cloneDeep(y);
console.log(c2 === y);
Info: 얕은복사와 깊은복사로 생성된 객체는 원본과는 다른 객체다.
- 객체의 값이 중첩된 경우
- 얕은복사→참조값 복사
- 깊은복사→중첩된 객체까지 모두 복사
7-프로퍼티 어트리뷰트
Info: 내부슬롯(internal slot), 내부 메서드(internal method)
- 자바스크립트의 구현 알고리즘 설명을 위해 ECMAscript 사양에서 사용하는 의사프로퍼티(pseudo property) , 의사 메서드(pseudo method)
- 표준사양 문서에 이중 대괄호(
[[…]]) 로 표시된 것이 내부슬롯과 내부 메서드 이다.
**7-1-**데이터속성설명자 defineProperty,defineProperties
Info: 정의: 객체 데이터 속성을 설명하는 것
자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동정의한다.
프로퍼티의 상태란 프로퍼티의 값, 수정/열거/재정의 여부를 말한다.
- 플래그 종류
| 종류 | 설명 |
|---|---|
| value | 값 |
| writable | 수정가능여부 |
| enumerable | 열거가능여부 |
| configurable | 재정의가능여부 |
7-1-1-****Object.getOwnPropertyDescriptors
객체의 모든 프로퍼티를 반환한다
const obj = {
a: 1,
b: 2,
c: 3,
}
console.log(Object.getOwnPropertyDescriptors(obj));
7-1-2-****Object.getOwnPropertyDescriptor()
지정한 프로퍼티를 반환한다
const obj = {
a: 1,
b: 2,
c: 3,
}
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
7-1-3-Object.defineProperty()
플래그로 프로퍼티의 속성의 쓰기 권한을 지정한다
const user = {}
Object.defineProperty(user, 'u_id', { value: 'member' })
console.log(Object.getOwnPropertyDescriptors(user));

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const user = {}
Object.defineProperty(user, 'name', {
value: 'old',
writable: false, //수정여부
enumerable: true, //순회가능여부
configurable: true// 설정(삭제가능) 변경여부
})
user.name= 'new'
console.log(Object.getOwnPropertyDescriptors(user));
</script>
</body>
</html>
코드러너에서는 오류가 날수 있으므로 html 문서로 작성하여 브라우저에서 테스트한다.
7-1-3-1-writable
user.name= 'new' 값 변경안됨
7-1-3-2-enumerable
객체자료형을 순회할때는 for~in 을 사용한다.
const user = {
name: 'abc',
age: '20',
rule: 'guest',
}
Object.defineProperty(user, 'name', {
writable: false, //수정여부
enumerable: false, //순회가능여부
configurable: false// 설정(삭제가능) 변경여부
})
for (let key in user) {
const textNode = document.createTextNode(key);
document.body.appendChild(textNode);
}

enumerable: true, 로 바꾸면

순회한다.
7-1-3-3-configurable
configurable: true 로 바꿔본다.
delete user.name;
console.log(user);

name 이 삭제됨
configurable: false 로 수정

삭제 안됨
7-1-4-defineProperties()
여러개의 프로퍼티를 한번에 정의할때는 Object.defineProperties() 메서드를 사용한다.
Object.defineProperties(user, {
name: {
writable: false,
enumerable: true,
configurable: false
},
age: {
writable: false,
enumerable: true,
configurable: false
},
rule: {
writable: false,
enumerable: true,
configurable: false
}
})
객체의 프로퍼티에 사용자 접근 방지시 사용할수 있다.
7-2-접근자 프로퍼티
7-2-1-get
{
const person = {
name: 'kim',
age: 20,
get profile() { return `${this.name}-${this.age} ` },
}
console.log(person.profile);
}
7-2-2-set
{
const person = {
name: 'kim',
age: 20,
get profile() { return `${this.name}-${this.age} ` },
** set profile(x) { [this.name, this.age] = x.split('-') }**
}
//console.log(person.profile("용-25"));
console.log(person.profile = "park-25");
}
8-메서드 체이닝
const calculate = {
value: 0,
add: function (n1) {
this.value += n1;
return this;
},
subtract: function (n1) {
this.value -= n1;
return this;
},
result: function () {
return this.value
}
}
const result = calculate.add(10).subtract(5).result();
console.log(result);
const calculate2 = {
add: function (n1, n2) { return n1 + n2 },
subtract: function (n1, n2) { return n1 - n2 },
multiply: function (n1, n2) { return n1 * n2 },
devide: function (n1, n2) { return n1 / n2 },
}
let n = 0;
const res1 = calculate2.add(n, 50)
const res2 = calculate2.subtract(res1, 50)
console.log(res2);
9-문제
출처:수코딩(https://www.sucoding.kr)
9-1. 객체 병합
문제
두 개의 객체를 병합하여 반환하는 함수를 작성하세요. 중복된 키가 있을 경우, 두 번째 객체의 값이 우선합니다. 입력:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
console.log(mergeObjects(obj1, obj2)); // { a: 1, b: 3, c: 4 }
const obj3 = { x: 10 };
const obj4 = { y: 20 };
console.log(mergeObjects(obj3, obj4)); // { x: 10, y: 20 }
const obj5 = { a: 1, b: 2 };
const obj6 = { a: 3, b: 4 };
console.log(mergeObjects(obj5, obj6)); // { a: 3, b: 4 }
const obj7 = {};
const obj8 = { z: 5 };
console.log(mergeObjects(obj7, obj8)); // { z: 5 }
답
function mergeObjects(obj1, obj2) {
const merge = {};
for (let key in obj1) {
merge[key] = obj1[key];
}
for (let key in obj2) {
merge[key] = obj2[key];
}
return merge;
}
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
console.log(mergeObjects(obj1, obj2)); // { a: 1, b: 3, c: 4 }
function mergeObjects(obj1, obj2) {
return { ...obj1, ...obj2 };
}
9-2. 키-값 배열화
문제
주어진 객체의 키-값 쌍을 배열로 반환하는 함수를 작성하시오. 입력:
const obj = { a: 1, b: 2, c: 3 };
console.log(objectToArray(obj)); // [['a', 1], ['b', 2], ['c', 3]]
const obj2 = { x: 5, y: 10 };
console.log(objectToArray(obj2)); // [['x', 5], ['y', 10]]
const obj3 = { p: 3 };
console.log(objectToArray(obj3)); // [['p', 3]]
const obj4 = {};
console.log(objectToArray(obj4)); // []
답
function objectToArray(obj) {
const result = [];
for (let key in obj) {
result.push([key, obj[key]]);
}
return result;
}
function objectToArray(obj) {
return Object.entries(obj);
}
9-3. 객체 값 필터링
문제
주어진 객체에서 값이 특정 기준 이상인 키-값 쌍만 필터링하여 반환하는 함수를 작성하세요 입력
const obj = { a: 1, b: 5, c: 3 };
const threshold = 2;
console.log(filterByThreshold(obj, threshold)); // { b: 5, c: 3 }
const obj2 = { x: 1, y: 2, z: 3 };
const threshold2 = 2;
console.log(filterByThreshold(obj2, threshold2)); // { y: 2, z: 3 }
const obj3 = { a: 10, b: 5, c: 1 };
const threshold3 = 6;
console.log(filterByThreshold(obj3, threshold3)); // { a: 10 }
const obj4 = { m: -1, n: 0, o: 1 };
const threshold4 = 0;
console.log(filterByThreshold(obj4, threshold4)); // { n: 0, o: 1 }
답
function filterByThreshold(obj, threshold) {
const result = {};
for (let key in obj) {
if (obj[key] >= threshold) result[key] = obj[key];
}
return result;
}
function filterByThreshold(obj, threshold) {
const result = {};
Object.entries(obj).forEach(([key, value]) => {
if (value >= threshold) {
result[key] = value;
}
});
return result;
}
9-4. 객체의 값 변화
문제
주어진 객체의 모든 값을 제곱하는 함수를 작성하세요 입출력
const obj = { a: 1, b: 2, c: 3 };
console.log(squareValues(obj)); // { a: 1, b: 4, c: 9 }
const obj2 = { x: 2, y: 3 };
console.log(squareValues(obj2)); // { x: 4, y: 9 }
const obj3 = { p: 0, q: -2 };
console.log(squareValues(obj3)); // { p: 0, q: 4 }
const obj4 = {};
console.log(squareValues(obj4)); // {}
답
function squareValues(obj) {
const result = {};
// 로직
for (let key in obj) {
result[key] = obj[key] * obj[key];
}
return result;
}
function squareValues(obj) {
const result = {};
// 로직
Object.keys(obj).forEach((key) => {
result[key] = obj[key] ** 2;
});
return result;
}
9-5. 객체에서 특정 키 삭제
문제
주어진 객체에서 특정 키를 삭제하는 함수를 작성하세요 입출력
const obj = { a: 1, b: 2, c: 3 };
const keyToDelete = 'b';
console.log(deleteKey(obj, keyToDelete)); // { a: 1, c: 3 }
const obj2 = { x: 10, y: 20, z: 30 };
const keyToDelete2 = 'y';
console.log(deleteKey(obj2, keyToDelete2)); // { x: 10, z: 30 }
const obj3 = { a: 5 };
const keyToDelete3 = 'a';
console.log(deleteKey(obj3, keyToDelete3)); // {}
const obj4 = { m: 1, n: 2, o: 3 };
const keyToDelete4 = 'p';
console.log(deleteKey(obj4, keyToDelete4)); // { m: 1, n: 2, o: 3 }
답
function deleteKey(obj, keyToDelete) {
const result = {};
for (let key in obj) {
if (key !== keyToDelete) result[key] = obj[key];
}
return result;
}
function deleteKey(obj, keyToDelete) {
const result = { ...obj };
delete result[keyToDelete];
return result;
}
9-6. 객체의 중복 값 제거
문제
주어진 객체에서 중복된 값을 제거하고, 그에 해당하는 키만 반환하는 함수를 작성하세요 입출력
const obj = { a: 1, b: 2, c: 1, d: 3 };
console.log(removeDuplicateValues(obj)); // { b: 2, d: 3 }
const obj2 = { x: 5, y: 5, z: 10 };
console.log(removeDuplicateValues(obj2)); // { z: 10 }
const obj3 = { p: 1, q: 1, r: 1 };
console.log(removeDuplicateValues(obj3)); // {}
const obj4 = { m: 3, n: 4, o: 3 };
console.log(removeDuplicateValues(obj4)); // { n: 4 }
답
function removeDuplicateValues(obj) {
const count = {}; // 값의 갯수를 세는 객체
const result = {}; // 최종 결과 객체
// 값이 몇번 등장했는지 계산
Object.values(obj).forEach((value) => {
count[value] = (count[value] || 0) + 1;
});
Object.keys(obj).forEach((key) => {
if (count[obj[key]] === 1) {
result[key] = obj[key];
}
});
return result;
}
9-7. 객체의 값으로 키 찾기
문제
주어진 객체에서 특정 값에 해당하는 키를 반환하는 함수를 작성하세요. 값이 여러 개일 경우, 첫 번째 키만 반환한다. 값이 없으면 null을 반환하세요 입출력
const obj = { a: 1, b: 2, c: 3 };
console.log(findKeyByValue(obj, 2)); // 'b'
console.log(findKeyByValue(obj, 4)); // null
console.log(findKeyByValue(obj, 1)); // 'a'
console.log(findKeyByValue({}, 1)); // null
답
function findKeyByValue(obj, value) {
for (let key in obj) {
if (obj[key] === value) return key;
}
return null;
}
function findKeyByValue(obj, value) {
const keys = Object.keys(obj);
for (let key of keys) {
if (obj[key] === value) return key;
}
}
9-8. 객체의 모든 값 곱하기
문제
주어진 객체의 모든 값들을 곱하여 반환하는 함수를 작성하세요. 입출력
const obj = { a: 1, b: 2, c: 3 };
console.log(multiplyValues(obj)); // 6
const obj2 = { x: 2, y: 3, z: 4 };
console.log(multiplyValues(obj2)); // 24
const obj3 = { a: 1, b: 0, c: 3 };
console.log(multiplyValues(obj3)); // 0
const obj4 = {};
console.log(multiplyValues(obj4)); // 1 (곱셈의 항등원)
답
function multiplyValues(obj) {
let result = 1;
for (let key in obj) {
result *= obj[key];
}
return result;
}
function multiplyValues(obj) {
let result = 1;
Object.values(obj).forEach((value) => {
result *= value;
});
return result;
}
function multiplyValues(obj) {
const values = Object.values(obj);
return values.reduce((acc, cur) => {
return acc * cur;
}, 1);
}