모던 자바스크립트 스터디 3주차 : 객체

leehyunju·2022년 6월 19일
1
post-thumbnail

https://ko.javascript.info/
4단원 객체에 대한 내용을 다룹니다.

객체

js에서는 총 7가지 자료형이 있다. 이 중 일곱 개는 오직 하나의 데이터만 담을 수 있어 '원시형' 이라고 한다.
하지만 객체형은 원시형과 달리 다양한 데이터를 담을 수 있다.
즉, 데이터 집합이나 복잡한 개체를 저장할 수 있다는 것

자바스크립트를 잘 다룰려면 객체를 잘 이해해야 한다.
객체는 중괄호 {...}를 이용해 만들 수 있다.

객체 형태

키(key): 값(value)

쉽게 비유하여 빈 객체는 빈 서랍이라고 할 수 있고, 프로퍼티는 물건이라고 할 수 있다.

// 객체 생성자 문법
let user = new Object();

// 객체 리터럴 문법
let user = {};

중괄호 {...} 안에는 키:값 쌍으로 구성된 프로퍼티가 들어간다.

let user = {     // 객체
  name: "me",  // 키: "name",  값: "me"
  age: 20        // 키: "age", 값: 20
};

ex)

let student = new Object();
let student = {
  name : "mike",
  age : "18"
};

프로퍼티 수정

let student = {};
user.name = "mike";
user.name = "마이콜";

객체의 프로퍼티는 let으로 선언하든 const (상수)로 선언하든 수정할 수 있다. 🙆🏻‍♀️


프로퍼티(= 사물함 속 물건) 삭제

delete student.age;

사물함(객체) 속 물건 (프로퍼티)을 들여다보고 싶다면, 점 표기법(.)을 사용하여 값을 읽을 수 있다.


접근법

  • 점 표기법 : 객체.프로퍼티
  • 대괄호 표기법 : 객체["프로퍼티"]

‘in’ 연산자로 프로퍼티 존재 여부 확인하기

사용 인터페이스

"key" in object

in을 사용하면 존재 여부를 알 수 있다. true, false로 존재 여부를 나타낸다.


‘for…in’ 반복문

for (key in object) {
  // 각 프로퍼티 키(key)를 이용하여 본문(body)을 실행합니다.
}

for in 문을 사용하면 객체의 모든 프로퍼티를 나열할 수 있다.

참조에 의한 객체 복사

원시값(문자열, 숫자, 논리형)은 값 그대로 저장 및 할당되고 복사되는 반면에 객체는 '참조에 의해' 저장되고 복사된다.

let message = "Hello!";
let phrase = message;

⭐️ 두 개의 독립된 변수에 각각 'Hello'가 저장된다. 변수엔 객체가 그대로 저장되는 것이 아닌, 객체가 저장되어있는 '메모리 주소'인 객체에 대한 '참조값'이 저장된다.

쉽게 말해, 객체의 참조 값만 복사되고 객체가 복사되는 것은 아니라는 것.

참조에 의한 비교

객체를 비교할 때는 동등 연산자(==)와 일치 연산자(===)는 동일하게 동작한다.
비교 시 피연산자인 두 객체가 동일한 객체인 경우 참을 반환한다.

let a = {};
let b = a; // 참조에 의한 복사

이런 경우, 참을 반환한다.

하지만, 독립된 객체는 일치 동등 비교하면 거짓이 반환된다.

let a = {};
let b = {}; // 독립된 두 객체

alert( a == b ); // false

내용물은 빈 객체로 동일하지만 어찌됐건 두 객체는 독립되어있기 때문이다.
위에 처럼 참조에 의한 복사를 할 경우에만 참을 반환한다.

객체 복사, 병합

Object.assign() 메소드

let b = a; 이런식으로 표현하면 객체에 대한 참조 값이 하나 더 만들어진다. 복사의 개념이다. 그런데, 기존에 있던 객체와 똑같고 독립적인 객체를 만들기 위한 '객체를 복제' 하고 싶다면 Object.assign을 사용한다.

문법 인터페이스

Object.assign(dest, [src1, src2, src3...])

첫번째 인수는 목표로 하는 객체이고, 대괄호로 싸여져 있는 인수들은 복사하고자 하는 객체이다. Object.assign을 사용하여 여러 객체를 하나로 병합할 수 있다.

지금까지 설명한 것이 얕은 복사의 개념이다.

얕은 복사 VS 깊은 복사

나는 객체중에서 가장 헷갈리는 부분이 얕은복사 깊은복사이다.
객체는 참조에 의해 할당되고 복사된다. 변수에는 객체가 아닌 메모리 상의 '참조'가 저장되는 것이다.

(1) 얕은 복사

얕은 복사는 객체를 복사할 때, 해당 객체만 복사하여 새 객체를 생성한다.
복사된 객체의 인스턴스 변수는 원본 객체의 인스턴스 변수와 같은 메모리 주소를 참조한다.

(2) 깊은 복사

객체를 복사할 때, 해당 객체와 인스턴스 변수까지 복사하는 방식이다. 전부를 복사하여 새 주소로 담기 때문에 참조를 공유하지 않는다.

그래서 깊은 복사는 ...(spread) 연산자를 통한 복사가 가능하다.

const a = {a:1, b:2};
cosnt b = {...a};

스프레드 연산자를 통해 중괄호 안에 a의 속성을 복사하여 b에 할당했다.
이제 a와 b는 완전 남남인 다른 주소를 갖게 된 것이다.

깊은 복사를 하기 위해서는 여러 방법들이 있다.

  • 재귀적으로 깊은 복사를 수행
  • lodash를 이용하여 cloneDeep 함수 사용
  • JSON.parse()와 JSON.stringify() 함수 사용
profile
아늑한 뇌공간 🧠

1개의 댓글

comment-user-thumbnail
2022년 6월 26일

객체를 복사할 때, 해당 객체와 인스턴스 변수까지 복사하는 방식이다. 전부를 복사하여 새 주소로 담기 때문에 참조를 공유하지 않는다.

그래서 깊은 복사는 ...(spread) 연산자를 통한 복사가 가능하다.


제가 저번주에 설명드린 내용이 많이 잘 못 되었던 것 같아요!

얕은 복사의 기본 개념은 메모리 주소의 복사, 깊은 복사는 값을 복사입니다.

자바스크립트의 객체의 경우에는 조금씩 의미가 달라질 수 있는데, 기본적인 할당을 통해서

객체를 복사할 경우

const obj = {};
const a = obj;

이렇게 되면 참조에 의한 복사이기 때문에 얕은 복사입니다.

const obj = {
};
const a = {...obj}
이렇게 할 경우 obj 가 빈 객체이기 때문에 깊은 복사가 됩니다.

그래서 1중첩인 객체의 경우 스프레드 연산자만 사용할 경우 깊은 복사가 가능합니다.

하지만 2중 이상의 중첩된 객체의 경우 스프레드 연산자를 사용하면 가장 바깥에 있는 프로퍼티들만 깊은 복사가 되기 때문에 내부의 객체는 메모리값이 복사되게 됩니다. (half 깊은 복사라고 생각하시면 될듯합니다.)
이것도 결국 얕은 복사로 치긴 합니다.

https://lunit.gitbook.io/redux-in-korean/recipes/structuringreducers/immutableupdatepatterns

그래서 스프레드 연산자는 예외가 있기 때문에 깊은복사가 안된다고 설명 드렸어야 되는데 헷갈려서 제대로 설명을 못 드렸네요.

답글 달기