자바스크립트 불변객체 (feat. 코어 자바스크립트)

JangGwon·2022년 7월 31일
0

본 포스팅은 코어 자바스크립트 책을 읽고 정리한 내용입니다.


1. 불변 객체

1-1 불변 객체가 왜 필요한가?

예시

var user = {
  	name : 'jjg',
 	gemder : 'male'
};

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

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

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

위의 상황은 복사한 객체에 값을 변경하였지만, 원본 값도 같이 변경된걸 볼 수 있는데, 그 이유는 user1, user2 변수 모두 같은 주소공간을 바라보고 있고, 그 주소 공간 중 프로퍼티 name이 가리키는 데이터를 변경하였기 때문에, user1 user2의 값이 같이 변경된 문제가 생겨버렸다. 이 경우를 대비하기 위해서는 복사한 객체를 변경하더라도 원본 객체는 그대로여야하는 경우가 필요한데, 그렇기 위해서는 불변객체가 필요하다.

1-2 불변 객체 만들기

1. 하드 코딩
var user = {
  	name : 'JJG',
  	gender: 'male'
};

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

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

console.log(user.name,user2.name);		// output : JJG kang
console.log(user === user2.name);		// output : false

단점. 복사하는 대상 객체에 정보가 많거나, 변경해야 할 정보가 많을수록 해야될 수고가 늘어난다.

2. 얕은 복사 (바로 아래 단계의 값만 복사하는 방식)
var copyObject = function(target) {
  	var result = {};
  	for (var prop in target) {
      	result[prop] = target[prop];
    }
  return result;
}

var user = {
  	name : 'JJG',
  	gender: 'male'
};

var user2 = copyObject(user);
user2.name = "Kang";

console.log(user.name,user2.name);		// output : JJG kang
console.log(user === user2.name);		// output : false

단점. 바로 아래 단계의 값만 복사하여, 복사하는 대상이 중첩된 객체의 하위 프로퍼티일때, 사본 데이터를 변경할 시 원본 데이터도 똑같이 변경되는 상황이 생길 수 있음.


2. 깊은 복사

2-1 깊은 복사가 왜 필요한가?

var user = {
  	name : 'JJG',
  	id : {
      		home : 'seoul'
    }
};

var user2 = copyObject(user);

user2.name = 'Kang';
console.log(user.name === user2.name);					 // output : false

user2.id.home = 'none';
console.log(user.id.home === user2.id.home);			 // output : true

user객체에 직접 속한 프로퍼티에 대해서는 복사해서 완전히 새로운 데이터가 만들어진 반면, 하위 프로퍼티 id에서는 기존 데이터를 그대로 참조하기 때문에 원본, 사본 데이터가 똑같이 변경된것을 볼 수 있다. 이런 현상이 발생하지 않게 하려면 하위 프로퍼티들도 불변 객체로 만들어야한다

2-2 깊은 복사는 어떻게하는가?

1. 재귀적인 방법으로 깊은복사를 수행하는 범용함수 만들기
var copyObjectDeep = function(target)  {
  var result = {};
  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,
	}
};
var obj2 = copyObjectDeep(obj);
obj2.a.c = 3;
console.log(obj) 			  // output : a :1 b : { c : null } 
console.log(obj2)			  // output : a :1 b : { c : 4  }
2. 객체를 JSON 문법으로 표현된 문자열로 만들었다가 다시 JSON 객체로 바꾸는 방법

(단, 메서드, 숨겨진 프로퍼티, getter/setter와 같이 json으로 변경할 수 없는 프로퍼티는 불가능)

3. hasOwnProperty 메서드를 활용해 프토타입 체이닝을 통해 상속된 프로퍼티의 복사를 막을수있음
4. ES6, ES2017에서는 Object.getOwnPropertyDescriptor와 Object.getOwnPropertyDescriptors를 통해 getter/setter를 복사 할 수 있음


참조

『코어 자바스크립트』 (정재남, 위키북스)

0개의 댓글