객체

key : value 의 쌍의 형태의 값을 갖는 자료형으로 key에는 문자/심볼형, value에는 모든 자료형이 올 수 있다.
이 때, 이 한 쌍을 프로퍼티(property)라고 부른다.



생성 방법

◾ new 키워드 이용 (사용자 정의 객체)

let user = new Object();

생성자 함수를 이용한 방식으로 생성자 함수 앞에 new키워드를 통해 생성이 가능하다.

◾ 리터럴 방식

let user = {};

중괄호 {}를 이용하여 생성해줄 수 도 있다.



특징

◾ 참조에 의해 저장, 복사 된다

let admin = { name: 'kim' };
let user = admin;

admin.name = 'hong';
console.log(user.name); //'hong'


◾ 프로퍼티의 key로 복수 단어도 가능하다

let user = {
  'first name': 'gildong',
};

key로 공백이 포함된 복수 단어도 가능한데 따옴표로 묶어줘야 사용이 가능하다.

user.'first name'; // error
user['first name']; // 'gildong'

만약, 복수 단어의 key라면 `점 표기법으로 값을 읽을 수 없다.


◾ 프로퍼티 key로 외부변수도 가능하다

객체를 생성할때 객체 리터럴 내에서 외부변수를 대괄호로 묶어 사용할 수 있는데 이런 프로퍼티를 계산된 프로퍼티라고 한다.

let key = 'name';

let user = {
  [key]: 'hong',
};


◾ 프로퍼티 value로 함수도 가능하다.

1. 객체 외부에서 할당

let user = {};
function sayHello() {
  console.log('Hello');
}

user.sayHi = function () {
  console.log('Hi');
};
user.sayHello = sayHello;

2. 객체 내부에서 선언

let user = {
     name : "hong"
     sayHi : function{
        console.log('Hi');
     },
     sayHello(){
       console.log('Hello');
     }
   };

객체 내부에서 함수를 선언할 때 ES6부터는 keyfunction키워드를 생략이 가능하다.


◾ const 객체더라도 내부의 프로퍼티 수정은 가능하다

const user = {
  'first name': 'gildong',
};
user = {}; //error
user['last name'] = 'hong'; //success

user라는 변수가 const인 것이지 user가 참조하고 있는 객체가 불변이 아니기 때문에 객체 내부는 수정이 가능하다.


◾ 존재하지 않는 프로퍼티에 접근해도 에러를 발생 시키지 않는다

let user = {};
console.log(user.name === undefined); //true

없는 프로퍼티에 접근할때 에러가 아닌 undefined를 반환 한다.


◾ 프로퍼티 key가 정수라면 자동 정렬 된다

let foo = {
  3: 3,
  a: 'a',
  1: 1,
};
console.log(foo); // {1: 1, 3: 3, a: 'a"}

◾ 논리 평가시 참을 반환한다

let user = {};
if (user) console.log('yes'); //yes



복제

let admin = { name: 'admin' };
let user = admin;

객체는 참조타입이기 때문에 위와 같이 복제를 하려고 하면 두 변수모두 같은 객체를 가리키게 된다.

새로운 객체변수에 참조가 아닌 값을 그대로 복제하고 싶다면 for문을 이용하여 프로퍼티를 복제하거나 Object.assign()함수를 이용하여 복제할 수 있다.

◾ for … in

for (let key in admin) {
  user[key] = admin[key];
}

for ... in 구문은 해당 객체내에 있는 모든 키를 순회하는 반복문이다.


◾ Object.assign()

Object.assgin(target, source);

let user = Object.assgin({}, admin);

source의 객체를 target의 객체로 복사하는 함수로써, target의 프로퍼티 key 중에서 source의 프로퍼티 key와 중복되는 것이 있으면 source의 프로퍼티 값으로 덮어씌운채로 복사가 된다.

let a = { a: 'a' };
let b = {};
let c = Object.assign(b, a);

console.log(b === c); //true

반환 타입으로 복사된 target객체를 반환한다.


let user = {
  name: 'hong'
  likes: {
    fruit: 'apple',
    baverage: 'coffe',
  },
};

let clone = Objcect.assgin({}, user);
clone.likes.fruit = 'banana';

console.log(user.likes.fruit); //banana
console.log(user.likes === clone.likes); // true

Object.assign메서드는 열거할 수 있는 프로퍼티만 복사가 되며, target 객체의 [[Get]], [[Set]]을 이용하여 프로퍼티의 값을 복사하기 때문에, 객체내의 프로퍼티 값이 객체를 가지고 있는 이중 객체라면 프로퍼티 값으로 참조형 값을 복사하게 되어 완전한 복사가 되지 않는다.

이런 객체안의 객체도 복사하는 방법을 깊은 복사(deep cloning)이라고 하며, 깊은 복사를 하는 방법에는 프로퍼티 값을 for문을 통해 한번 더 검사하거나, lodash라이브러리의 _.cloneDeep(obj)를 이용하거나, JSON.parse(JSON.stringify(obj))와 같이 객체를 json형태로 바꾸었다가 다시 객체로 바꾸는 방법이 존재한다.



기타 메서드

◾ Object.fromEntries(iterable)

Array, Map, Set과 같은 반복 가능한 객체를 객체로 바꿔주는 메서드