본문 바로가기

개인적으로 공부한 것을 정리해 놓은 블로그입니다 틀린 것이 있으면 댓글 부탁 드립니다!


JAVASCRIPT

javascript 공부 9 - 기본개념5(Immutablility ,얕은 복사와 깊은 복사 )

반응형

JS 에서의 Immutablility

 

데이터의 불변성을 의미한다

 

자바스크립트에서의 데이터는 아래와 같이 분류할 수 있다.

 

원시 데이터 : String, Number, Boolean , undefined ,null

참조형 데이터 : Object , Array , Function

 

원시데이터 타입은 불변성을 갖고있다 이는 메모리 구조와 연관이 있다 . 

 

아래 표를 메모리라고 생각해 보면 각 칸의 1,2,3,4 는 주소값을 의미한다.

1:   1 2:    4 3:  4:

 

let a = 1;  

 

let b = 4; 

 

위의 두 코드가 한줄씩 실행된다고 생각하면

 

첫번째 줄에서 1이란 값이 1번방으로 들어가고 a라는 변수는 1번방의 주소값을 가리킨다

 

두번째 줄에서 4란 값이 2번방으로 들어간다  b라는 변수는 2번방의 주소값을 가리킨다.  

 

만약 아래와 같은 코드가 추가 된다면

 

let c = 1 ;

 

3번방에 1이 추가가 되는 것이 아니라 변수 c는  1이란 값이 메모리에 저장되 있는 1번방을 가리킨다.  데이터가 추가되거나 변하지 않고 

 

변수가 가리키는 주소값만 할당이 되는 것이다. 

 

이떄 중요한 것은  변수 a와 c 가 같은 주소값을 가리키고 있는 상태에서 

아래와 같이 c의 값을 바꾼다고 해도 1번방의 값이 바뀌는 것이 아니라 5는 3번방에 새롭게 저장되고  변수 c는 3번방을 가리키게된다.

 

c = 5; 

 

이를 데이터가 불변하다고 한다

 

원시데이터는 위와 같이 불변성을 갖고 있어 사용하는데에 편리하다 . 

 

 

 

 

반면에 참조형 데이터는 새로운 데이터가 만들어질 때마다 새로운 메모리 주소에 할당되기 때문에 값이 같다하더라도 객체 자체는 다르다

문제는 a와 b가 같은 주소값을 가리킬때 생긴다.  b = a ; 부분에서 b는 a가 가리키는 주소값을 가리키게 된다 (값이 복사되는 것이아니다) a와 b는 같은 주소값을 가리키고 b를 변경한다면 a도 변경되는 문제가 발생한다 .

 이를 가변하다고 하고 , 객체형 데이터 타입을 사용할 떄 주의해야 할 점이다 . 

 

//데이터 불변성 (immutability)

let a = {a:1 , b:2}

let b = {a:1 , b:2}

//같은 주소 값을 가리키게 된다

b = a;

console.log(a === b)

b.a = 10;

// 같은 주소 값을 가리키기 때문에 
// b의 값을 바꾸면 a값도 변한다.
console.log(a.a)

 

 

 

이를 해결하기 위해선 만약 객체형 데이터를 다른 변수에 할당하고 싶다면  할당연산자로 할당해주는 것이아니라 

 

값을 복사해 주어야 한다 . 

 

 

얕은복사와(shallow copy) 깊은복사(Deep copy)

 

 

얕은복사와(shallow copy)

 

객체의 겉만 복사하고 객체안에  다른 객체데이터는 복사되지 않는다.  

 

const user =  {
    name : 'ugo',
    age : 40,
    emails:['ugo@test.com']
}

console.log('-----------얕은복사---------')
//얕은 복사

//Object.assign() 메서드를 사용해서 값을 복사해줬다
const copyUser = Object.assign({}, user) ;
//전개 연산자를 사용해서 아래와 같이 할 복사할 수 도 있다.
const copyUser2 = {...user}
console.log(copyUser === user);


user.age = 22 
console.log(user)
console.log(copyUser)

 

위의 copyUser 는  user를  Object.assign() 메서드로 복사한 객체이다  메서드의 첫번째 파라미터로 target이  되는 빈 객체와 , 두번째 파라미터로 source가 되는 user를 제공해서 빈 객체에 user의 값들이 복사되었다.

copyUser2 처럼 spead 문법으로 {...user}으로도 복사할 수 있다. (user의 프로퍼티들이 빈 객체에 담긴다.)

copyUser === user 는 false 가 나온다

 

하지만 source 객체인 user 안의 emails는 value 로 객체데이터 타입인 array를 갖고있다 위에서 말한것 처럼 얕은 복사에서는 객체안의 객체데이터타입은 복사되지 않기 떄문에 user.emails === copyUser.eamils는 true 가 나온다 . 

 

이를 해결하기위해 객체안의 데이터들까지 복사하는 깊은복사를 사용한다

 

 

깊은복사(Deep Copy)

 

특정 참조데이터 내에 또 다른 참조데이터가 들어갈때 깊은 복사가 필요하다 . 순수 자바스크립트로 깊은 복사를 구현할 수 있지만 

lodash라는 라이브러리를 통해 편리하게 깊은복사가 가능하다 . 

 

npm i lodash  

 

위의 명령어를 통해 lodash를 인스톨하고 사용하려는 파일에서 임포트 해준다 

 

import _ from 'lodash' 

 

변수명을  '_' 로 해주는 것이 lodash를 사용할때의 룰이다. 

 

const copyUserDeep = _.cloneDeep(user);

console.log(copyUserDeep === user); 
console.log(copyUserDeep);
console.log('isSame:',copyUserDeep.emails === user.emails)

 

_.cloneDeep(소스 데이터) 메소드로 깊은 복사를 할 수 있다 . 

 

결과

 

 

안쪽에 있는 객체데이터인  array를 원본과 비교하면 false(isSame) 가 나온다  안쪽에 있는 객체데이터까지 복사가 잘 되었다. 

 

https://lodash.com/

 

Lodash

_.defaults({ 'a': 1 }, { 'a': 3, 'b': 2 });_.partition([1, 2, 3, 4], n => n % 2);DownloadLodash is released under the MIT license & supports modern environments. Review the build differences & pick one that’s right for you.InstallationIn

lodash.com

 

lodash의 사이트이다 lodash는 복사뿐만 아니라 여러가지 객체데이터에 대한 다양한 기능들을 제공해준다 . 

반응형