여니의 프로그래밍 study/JavaScript

4-2 참조에 의한 객체 복사 (Javascript)

여니's 2021. 3. 11. 14:50

 

참조란?

객체의 실제 위치를 가리키는 포인터

 

복제는 똑같은 파일(100MB)을 한 개 더 생성하는 것

> 각각의 파일이고,

원본 파일을 변경해도 복제 파일에는 아무런 영향이 없다.

메모리는 똑같이 100MB씩이고!

(복제!=복사)

 

참조는 복제와 다르다

참조는 바로가기 만들기를 이용해서 예시를 들어보자

바로가기 만들기는 원본 파일을 가리키고 있을뿐,

복제한 게 아니다.

따라서 바로가기 파일에서 값을 변경하면,

원본 파일도 변경이 동시에 이루어진다.

 


 

객체는 참조에 의해 저장되고 복사 된다.

원시값(문자열, 숫자, 불린 값,null,undefined)은

값이 그대로 저장,할당,복사가 된다

이 때는 두 개의 독립된 변수에 각각 문자열이 저장된다.

복사된 값을 다른 메모리에 각각 할당하기에 서로 영향을 미치지 않는다.

 

변수에는

객체가 저장되어 있는 '메모리 주소'인

객체에 대한 '참조 값'이 저장된다.

 

따라서 객체가 할당된 변수를 복사할 땐,

객체의 참조 값이 복사되는 것이지

객체가 복사되는 게 아니다!

 

user.name은 admin 참조값에 의해 변경되었다.

>> 결과값 : lion,lion

 


참조에 의한 비교

객체 비교시 동등연산자 ==와 일치 연산자===는 동일하게 작용한다.

일치 연산자가 동등 연산자와 다른 점은,

자료형까지 구분한다는 점이다.

 

※ 대소 비교나 원시값과의 비교에선 객체가 원시형으로 변환된다.

 

a와 b는 모두 같은 객체를 참조하니까 true 값 반환

 


결과값 false, false

객체가 비어있어서 같아보이지만,

각각 독립된 객체이기 때문에

거짓이 반환된다.

 

102호, 103호가 비어있다고 해서

같은 집이라고 할 수 없는 것처럼!

 


객체를 복제하고 싶다면?

(사실 참조에 의한 복사로 해결이 가능해서 객체를 복제할 일은 거의 없다)

 

정말 복제가 필요한 상황이라면,

새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 원시 수준까지 프로퍼티를 복사한다.


1. 첫 번째 방법

1. 먼저 빈 객체를 생성한다.

2. 기존 객체(user)의 프로퍼티들을 순회해서 프로퍼티를 전부 복사해 넣는다.

>> 이로 인해 clone 객체는 완전히 독립적인 복제본이 되었다.

 


복사 (copy)

in python

b_list는 a_list가 참조하고 있는 값을 똑같이 참조한다.

(따라서 주소값이 같다)


얕은 복사 (Shallow copy)

: 원래 값과 복사된 값이 같은 참조를 가리키고 있는 것

대표객체는 복사하지만, 하위 객체는 참조만 하는 방법

 

: 첫 번째 인자로 들어오는 객체에 두 번째 인자로 들어오는 객체의 프로퍼티들을

차례대로 덮어쓰기하여 반환하는 메소드이다.

프로퍼티의 참조를 복사하기 때문에,

오브젝트 안에 오브젝트 또는 배열이 있을 경우 복사가 아닌 참조를 하게 된다.

따라서 객체를 비교했을 때는 다른 값이지만, 하위 객체는 같은 값이다.

 

m.blog.naver.com/wideeyed/221789258087

 

[JavaScript] 자바스크립트객체 복사하기 (앝은 복사, 깊은 복사)

자바스크립트객체(Object)는 Key(키):Value(값)의 1개 또는 여러 쌍으로 구성됩니다.Value(값)에는 숫...

blog.naver.com

- Object.assign()

복사도 할 수 있고,

여러 객체를 하나로 병합할 수도 있다.

Object.assign( 목표로 하는 객체명, 객체1, 객체2,..);

 

- spread()

 


깊은 복사 (Deep copy)

: 객체안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체

대표 객체 뿐만 아니라 하위 객체까지 복사하는 방법이다.

객체와 하위 객체 모두 새로 복사되어 다른 곳을 가리킨다.

ex) 재귀함수 이용한 복사, JSON.stringify(), 라이브러리 사용

 

- JSON 객체의 메소드를 이용

: JSON.parse(JSON.stringify(obj));

JSON.stringify > 자바스크립트 오브젝트를 스트링 포맷으로 변환함

JSON.parse : 스트랭 포맷을 자바스크립트 오브젝트로 변환

> 왜 번거롭게 변환을 하냐면!?

object -> string -> object 변환 과정을 거치면서

이전 객체에 대한 참조가 없어진다.

하지만 JSON 메소드 자체가 성능면에서 굉장히 느림에 주의!

 

 

- 자바스크립트 재귀 사용

: 오브젝트의 프로퍼티들을 순회하면서 빈 오브젝트에 더한다.

그 과정에서 원본 오브젝트의 프로퍼티가 오브젝트일 경우

재귀적으로 함수를 실행한다.

 

 

 


Immutable.js

Impirent.js는

List, stack, map, orderedMap, Set, OrderSet and Record를 포함한

많은 영구 불변 데이터 구조를 제공합니다.

>> JS의 값을 불변객체로 만들 수 있게 도와준다.

 

- 불변 객체

: 생성 후 그 상태를 바꿀 수 없는 객체

원시 타입은 변경 불가능한 값 (immutable value)

원시 타입 이외의 모든 값(객체)은 변경 가능한 값(mutable value)

 

굳이 immutable을 쓰는 이유가 뭘까??

=> immutable로 객체를 선언하고 사용하게 되면,

객체의 메모리 주소가 불변하기 때문에,

구조를 단순하게 유지할 수 있고 ,

그로 인해 구조적인 공유를 할 수 있어서

애플리케이션을 추론하기 쉽게 된다.

 

- 애플리케이션

: 특정 목적을 위해 제작된 프로그램

 

{}와 [] 대신, Map, List라는 새로운 객체를 제공한다.

 

Map(객체) : key와 value

List(배열) : Array

Stack : stack 형태로 동작하지만, array의 동작의 대부분 사용 가능

Set(설정) : value와 value

Seq : Collection의 지연 평가를 제공

Range : 시작과 종료 값을 받아 Infinity Array를 제공

Repeat : 값을 받아 Infinity Array 제공

Record : 기본값을 기억하는 Record.Factory를 반환한다.

get : 읽을때

update : 읽은 다음에 설정 할 때

setIn,getIn,updateIn : 내부에 있는걸 ~할 땐 In을 붙인다.

delete : 특정 key를 지울 때