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) 가 나온다 안쪽에 있는 객체데이터까지 복사가 잘 되었다.
lodash의 사이트이다 lodash는 복사뿐만 아니라 여러가지 객체데이터에 대한 다양한 기능들을 제공해준다 .
'JAVASCRIPT' 카테고리의 다른 글
javascript 공부 8 - 기본개념4 (Object 클래스의 메서드들, 비구조화 할당(Destructuring assignment) , 전개 연산자) (0) | 2021.08.06 |
---|---|
javascript 공부 7 - 기본개념3 (배열을 다루는 메서드들) (0) | 2021.08.06 |
javascript 공부 6 - 기본개념2(클래스 , this, ES6의 class , 상속) (0) | 2021.08.06 |
javascript 공부 5 - 기본개념1(화살표 함수 , IIFE(즉시 실행 함수) , 호이스팅 , 타이머 함수, 콜백) (0) | 2021.08.06 |
javascript 공부 3 - 형 변환(Type conversion) (0) | 2021.08.05 |