공부 및 일상기록

[Javascript] 객체와 불변성이란? 본문

개발/Javascript

[Javascript] 객체와 불변성이란?

낚시하고싶어요 2022. 9. 23. 16:51

1. 기본형 데이터와 참조형 데이터

  • 기본형(Primitive type) : 값을 그대로 할당
    • 메모리 내에 고정된 크기로 저장되면서, 원시 데이터 값 자체를 보관, 불변적 기본적으로 데이터는 하나의 메모리를 사용한다.(재사용)
    • Number
    • String
    • Boolean
    • null
    • undefined
    • Symbol (ES6 부터 추가 되었다. 객체 속성을 만드는 데이터 타입)
  • 참조형(Reference type) : 값이 저장된 주소 값을 할당
    • Array(배열) : const로 선언된 변수 배열에  Array.push를 적용할 수 있는 이유가 배열은 참조타입이기에 데이터의 주소를 대입할 수 있다.
    • function(함수) / RegExp(정규표현식) : 문자열에 나타나는 특정 문자조합과 대응시키기 위해 사용되는 패턴
    • Map

2. 얕은 복사와 깊은 복사

  • 얕은 복사 (Shallow copy)
  • 얕은 복사란 객체를 복사할때 객체를 직접 대입하는 경우 참조에 의한 할당이 이루어져서 둘이 같은 주소를 가지고 있는 것이다.
const obj1 = { a:1 , b:2};
const obj2 = obj1
// 위 처럼 객체를 직접 대입하는경우 참조에 의한 할당이 이루어짐 (같은 주소를 참조)
obj2.a=100;
console.log(obj1.a);   //100
  • 위 두 객체는 같은 주소를 참조하고 있기 때문에 obj2의 property를 수정 후 obj1을 출력해도 둘은 같다.
  • 깊은 복사(deep copy)
  • 얇은 복사와 달리 아예 새로운 객체안의 속성(property)만 복사해서 사용하는 것이다.

 

  • 1. ...(spread) 연산자를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = { ...obj };
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
  • 위처럼 ...(spread) 연산자를 통해 새로운 {  }안에 obj1의 속성을 복사하여 obj2에 할당하면 다른 주소를 갖는다.
  • 단 이는 딱 1depth 까지만 이다.

 

  • 2. Object.assign() 메소드를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
  • Object.assign() 메소드를 통해 첫 번째 인자로 빈 { } 객체를, 두 번째 인자로 obj1 넣고 obj2 에 할당하였다.
  • 단 이는 딱 1depth 까지만 이다.

3. 불변 객체를 만드는 방법

  • 불변객체
  • 기본형 데이터를 변경하면 데이터는 변하지 않는다. 참조형 데이터도 새로운 데이터를 할당하면 변경되지 않는다.
  • 그러나 참조형 데이터인 객체를 복사하여 내부 프로퍼티를 수정한 경우 가변성이라는 성질에 의해 기존 객체도 변하게 된다.
  • 객체를 복사해서 내부 프로퍼티를 변경하고 싶지만 원본객체를 유지하고 싶을때는 불변객체를 만들어야 한다.
var student = {
    name : "coder_h",
    ban : 3,
    gender : 'male'
}

var copyObject = function(target){ // (1)
    var result = {};
    for(var prop in target){
        result[prop] = target[prop];
    }
    return result;
}

var student2 = copyObject(student);

student2.name = "kim";


console.log(student === student2); // false
console.log(student.name, student2.name); // coder_h kim
  • 위처럼 새로운 객체를 만들어 속성값만 복사하는 경우 기존 객체와 복사한 객체는 다른 객체가 된다.
  • 하지만 만약 아래 코드처럼 기존 객체 내부 속성중에 객체가 또 존재 하는경우 위 방법은 문제가 생긴다.
var student = {
    name : "coder_h",
    ban : 3,
    gender : 'male',
    friend : { // 새로 추가한 프로퍼티 (1)
        name : "hello"
    }
}

var copyObject = function(target){
    var result = {};
    for(var prop in target){
        result[prop] = target[prop];
    }
    return result;
}

var student2 = copyObject(student);

student2.name = "kim";
student2.friend.name = "Bye"; // student2의 친구이름을 변경 (2)


console.log(student === student2); // false
console.log(student.name, student2.name);// coder_h kim
console.log(student.friend.name, student2.friend.name); // Bye Bye (3)
  • 위 코드의 문제는 속성을 복사면서 내부의 객체를 또 복사한 셈이기 때문에 내부 속성에서 주소를 또 참조하게된다.
  • 이것이 1depth 까지만 깊은 복사가 된것이다.
  • 따라서 아래처럼 재귀복사를 하도록 코드를 만들어야 완전한 불변객체로 역할을 할수있다.
var student = {
    name : "coder_h",
    ban : 3,
    gender : 'male',
    friend : {
        name : "hello"
    }
}

// 깊은복사 (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 student2 = copyObjectDeep(student);

student2.name = "kim";
student2.friend.name = "Bye"; // (2)


console.log(student === student2);
console.log(student.name, student2.name);
console.log(student.friend.name, student2.friend.name); // hello Bye (3
  • 위 코드의 경우 target(복사할객체)를 result(잠시 복사해둘 객체)에 속성들 하나하나 for..in문을 통해 복사하는데 복사하는 속성이 또 객체인 경우 그 객체 또한 새로운 result를 만들어 속성을 복사해주는 방식이다. 이처럼 재귀적인 방식을 통해 원본 객체의 속성을 복사하면서도 원본 내부에 있는 객체들 또한 객체 자체가 아니라 그 속성들만 복사하게 되는것이다.
  • 이 함수를 이용하면 원본객체를 result 안에 완전히 새롭게 속성들만 배치했으므로 같은 속성의 다른 두 객체가 된다.
  • 따라서 student 객체와 student2 객체는 완전히 다른 객체가 되었다. (서로 참조하는 주소가 없음)

 

불변객체를 만드는 방법은 더 다양하다고 한다. 지금은 코딩을 시작한지 겨우 일주일이 지나고 있을 뿐이고 앞으로 더욱 공부해야겠다.

 

 

위 글은 저의 공부용으로 요약한 것이고 글은 하기의 블로그 등에서 자료를 가져왔습니다.

https://developeonmyown.tistory.com/m/321

 

[코어자바스크립트] 01. 불변 객체, 넌 누구냐?

기본형, 참조형 자바스크립트의 데이터 타입에는 크게 두 가지, 기본형 데이터 타입(Primitive type), 참조형 데이터 타입(Reference type)이 있다. 불변값 JavaScript에서 모든 기본형 데이터 타입은 불변값

developeonmyown.tistory.com

https://hanamon.kr/javascript-shallow-copy-deep-copy/

 

[JavaScript] 얕은 복사(shallow copy) vs 깊은 복사(deep copy) - 하나몬

💡 얕은 복사(shallow copy) vs 깊은 복사(deep copy) ❗️얕은 복사(shallow copy)란? const obj1 = { a: 1, b: 2}; const obj2 = obj1; console.log( obj1 === obj2 ); // true 위의 예시처럼 객체를 직접 대입하는 경우 참조에 의

hanamon.kr

https://velog.io/@recordboy/JavaScript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACShallow-Copy%EC%99%80-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACDeep-Copy

 

[JavaScript] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)

깂은 복사와 얕은 복사에 대해 알아보겠다. 이 글의 초반 내용은 이전 포스팅의 (원시 타입과 참조 타입의 차이과 맥락이 비슷하며, 위 포스팅은 원시 타입과 참조 타입의 차이점이라면 아래는

velog.io

https://velog.io/@hazzang/JS-%EC%8B%9C%EB%A6%AC%EC%A6%88-%EB%B6%88%EB%B3%80-%EA%B0%9D%EC%B2%B4

 

JS 시리즈 - 불변 객체

자바스크립트에는 기본형 데이터와 참조형 데이터가 있습니다.기본형 데이터를 변경하면 데이터는 변하지 않습니다. (불변성) 마찬가지로 참조형 데이터도 데이터 자체를 변경하고자 하면 즉,

velog.io