도서/코어 자바스크립트

1장. 데이터 타입 (04. 기본형 데이터와 참조형 데이터 - 불변 객체)

2023. 4. 11. 15:24
목차
  1. 불변 객체
  2. 얕은 복사와 깊은 복사

불변 객체

불변 객체를 만드는 간단한 방법

  • 참조형 데이터의 '가변'은 데이터 자체가 아닌 내부 프로퍼티를 변경할때 성립합니다.
  • 데이터 자체를 변경하고자 하면(새로운 데이터를 할당하고자 하면) 기본형 데이터와 마찬가지로 기존 데이터는 변하지 않습니다.

 

  1. 내부 프로퍼티를 변경할 필요가 있을 때마다 매번 새로운 객체를 만들어 재할당하기로 규칙을 정하거나
  2. 자동으로 새로운 객체를 만드는 도구를 활용하면

객체의 불변성을 확보할 수 있습니다.

 

  • 불변 객체가 필요한 경우
var user = {
  name: 'Jaenam',
  gender: 'male'
};

var changeName = function (user, newName) {
  var newUser = user;
  newUser.name = newName;
  return newUser;
};


var user2 = changeName(user, 'Jung');

if(user !== user2) {
  console.log('유저 정보가 변경되었습니다.'); // 미출력
}

console.log(user.name, user2.name); // Jung Jung
console.log(user === user2); // true

user2만 변경했지만 user1과 user2가 동일하게 변경되어 console.log가 출력되지 않습니다.

 

 

  • 객체의 가변성에 따른 문제점의 해결 방법
var user = {
  name: 'Jaenam',
  gender: 'male'
};

var changeName = function (user, newName) {
  return {
    name: newName,
    gender: user.gender
  };
};


var user2 = changeName(user, 'Jung');

if(user !== user2) {
  console.log('유저 정보가 변경되었습니다.'); // 유저 정보가 변경되었습니다.
}

console.log(user.name, user2.name); // Jaenam Jung
console.log(user === user2); // false

changeName 함수가 새로운 객체를 반환하도록 수정했습니다.

하지만 특정 객체에 대한 처리만 가능합니다.

 

 

  • 기존 정보를 복사해서 새로운 객체를 반환하는 함수 (얕은 복사)
var copyObject = function (target) {
  var result = {};
  for (var prop in target) {
    result[prop] = target[prop];
  }
  return result;
};

for ... in 문법을 이용해 result 객체에 target 객체의 프로퍼티들을 복사하는 함수입니다.

개선점은 있으나 user 객체에 대해서는 문제가 되지 않으므로 일단 진행합니다.

개선점
1. 프로토타입 체이닝 상의 모든 프로퍼티를 복사합니다.
2. getter/setter는 복사하지 않습니다.
3. 얕은 복사만을 수행합니다.
등등

 

 

  • copyObject를 이용한 객체 복사
var user = {
  name: 'Jaenam',
  gender: 'male'
};

var user2 = copyObject(user);
user2.name = 'Jung';

if(user !== user2) {
  console.log('유저 정보가 변경되었습니다.'); // 유저 정보가 변경되었습니다.
}

console.log(user.name, user2.name); // Jaenam Jung
console.log(user === user2); // false

copyObject만 사용한다고 규칙을 만들더라도 사람은 언제나 실수 할 수 있기 때문에,

시스템적으로 제약을 걸 수 있는 라이브러리들이 등장했습니다.

immutable.js, baobab.js 등등

 

얕은 복사와 깊은 복사

얕은 복사shallow copy: 바로 아래 단계의 값만 복사하는 방법

깊은 복사deep copy: 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법

 

  • 중첩된 객체에 대한 얕은 복사
var user = {
  name: 'Jaenam',
  urls: {
    portfolio: 'http://github.com/abc',
    blog: 'http://blog.com',
	facebook: 'http://facebook.com/abc'
  }
};

var user2 = copyObject(user);

user2.name = 'Jung';
console.log(user.name === user2.name); // false

user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true

user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog); // true

user2의 name 프로퍼티를 변경해도 user의 name프로퍼티는 변경되지 않습니다.

하지만 urls 프로퍼티를 어느쪽에서든 변경하면 동일하게 변경됩니다.

user 객체의 바로 아래에 속해있는 프로퍼티는 완전히 새로운 데이터가 만들어지지만,

한 단계 더 들어간 urls의 프로퍼티들은 기존 데이터를 그대로 참조합니다.

매번 여러단계의 프로퍼티를 위해 복사하기는 번거롭습니다.

 

 

  • 객체의 깊은 복사를 수행하는 범용 함수
var copyObjectDeep = function(target) {
  var result = {};
  // target !== null 이유: typeof 연산자가 null에 대해서도 'object'를 반환하기 때문!
  if(typeof target === 'object' && target !== null) {
    for(var prop in target) {
      result[prop] = copyObjectDeep(target[prop]);
    }
  } else {
    result = target;
  }
    return result;
};

 

  • 깊은 복사 결과 확인
var obj = {
  a: 1, 
  b: {
    c: null,
    d: [1, 2]
  }
};

var obj2 = copyObjectDeep(obj);

obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;

console.log(obj); // { a: 1, b: { c: null, d: [1, 3] } };
console.log(obj2); // { a: 3, b: { c: 4, d: { a: 1, 1: 2 } } };

 

  • JSON 객체를 문자로 변환 → 파싱하여 깊은 복사
var copyObjectViaJSON = function (target) {
  return JSON.parse(JSON.stringify(target));
};

var obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
    func1: function () { console.log(3); }
  },
  func2: function () { console.log(4); }
};

var obj2 = copyObjectViaJSON(obj);

obj2.a = 3;
obj2.b.c = 4;
obj.b.d[1] = 3;

console.log(obj); // { a: 1, b: { c: null, d: [1, 3], func1: f() }, func2: f() };
console.log(obj2); // { a: 3, b: { c: 4, d: [1, 2] } };

 

 

출처 : 코어 자바스크립트

 

코어 자바스크립트 - YES24

자바스크립트의 근간을 이루는 핵심 이론들을 정확하게 이해하는 것을 목표로 합니다최근 웹 개발 진영은 빠르게 발전하고 있으며, 그 중심에는 자바스크립트가 있다고 해도 결코 과언이 아니

www.yes24.com


잘못되어 수정해야 하거나 피드백 주실 부분이 있으시면 언제나 환영입니다!

 

'도서 > 코어 자바스크립트' 카테고리의 다른 글

1장. 데이터 타입(04. 기본형 데이터와 참조형 데이터 - 변수 복사 비교)  (0) 2023.04.10
1장. 데이터 타입 (04. 기본형 데이터와 참조형 데이터 - 불변값, 가변값)  (0) 2023.04.08
1장. 데이터 타입 (01. 데이터 타입의 종류 ~ 03. 변수 선언과 데이터 할당)  (0) 2023.04.07
  1. 불변 객체
  2. 얕은 복사와 깊은 복사
'도서/코어 자바스크립트' 카테고리의 다른 글
  • 1장. 데이터 타입(04. 기본형 데이터와 참조형 데이터 - 변수 복사 비교)
  • 1장. 데이터 타입 (04. 기본형 데이터와 참조형 데이터 - 불변값, 가변값)
  • 1장. 데이터 타입 (01. 데이터 타입의 종류 ~ 03. 변수 선언과 데이터 할당)
이토.
이토.
이토의 개발 관련 블로그
이토.
이토의 개발일지
이토.
전체
오늘
어제
  • 분류 전체보기 (10)
    • 도서 (7)
      • Learn Docker in a month of .. (3)
      • 코어 자바스크립트 (4)
    • 자바스크립트 (1)
    • Project (2)
      • Prostargram (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 자바스크립트
  • eventloop
  • 책
  • 도커
  • 이벤트루프
  • docker
  • javascript
  • 코어자바스크립트
  • requestAnimationFrame
  • 비동기
  • 스레드
  • devops

최근 댓글

최근 글

hELLO · Designed By 정상우.
이토.
1장. 데이터 타입 (04. 기본형 데이터와 참조형 데이터 - 불변 객체)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.