(JS) 모던 자바스크립트 Deep Dive - 4. 원시 값과 객체의 비교

2023. 6. 22. 01:08

11.1 원시 값

  • 원시 타입의 값에는 7종류, string, number, bigint, boolean, undefined, symbol, null이 있다. 
  • 원시 타입의 값은 변경 불가능하다. (불변성)
  • 원시 값을 변수(메모리 공간)에 할당하면 실제 값이 저장된다.
  • 원시 값을 다른 변수에 할당하면 원시 값이 복사되어 전달된다. (값에 의한 전달) 
  • 복사된 값에서 어떤 작업을 해도 원본에는 영향을 주지 않는다. (데이터의 신뢰성 보장)
    var score = 80;
    var copy = score;
    console.log(copy) // 80

    score = 10;

    console.log(score) // 10
    console.log(copy) // 80

2번째 줄에서 변수에 변수를 할당했다.
이제 변수 copy에는 변수 score의 원시 값이 복사되어 전달된다. (값에 의한 전달)
이후 변수 score의 값이 계속 변경되어도, 변수 copy의 값에는 score 값이 영향을 줄 수 없다.  

 

11.2 객체 

  • 객체 타입의 값에는 객체, 배열, 함수, 내장함수 Date, 정규표현식, Map, Set .. 등이 있다. 
  • 객체 타입의 값은 변경 가능하다.
  • 객체 값을 변수(메모리 공간)에 할당하면 참조된 값이 저장된다.
  • 객체 값을 다른 변수에 할당하면 참조된 값이 복사되어 전달된다. (참조에 의한 전달)
  • 객체는 변경 가능한 값이므로 메모리에 저장된 객체를 직접 수정이 가능하다.
  • 재할당 x 수정 o 이기 때문에 변수의 참조 값은 변경되지 않는다. 
  • 객체는 메모리의 효율적인 소비가 가능하다. 신뢰성은 조금 떨어지더라도 비용을 절약할 수 있다. 
  • 단, 원시 값과 다르게 여러 식별자가 하나의 객체를 공유할 수 있어서 위험하다.

 

11.2.1 얕은 복사 (Shallow Copy)

  • 객체나 배열을 복사하는 방법 중 하나.
  • 원본 객체 타입의 참조값만 복사해서 새로운 객체 타입을 생성한다.
  • 복사된 객체는 원본의 프로퍼티를, 배열은 원본의 요소를 참조한다. 
  • 복사된 객체, 배열의 프로퍼티,요소를 수정하면 원본 객체, 배열에도 영향을 준다.
  • const obj = { x: {y: 1}} 일 때, 스프레드 문법 {...obj} 혹은 Object.assign({}, obj)를 하면 된다.
  • const arr = [x,y,z] 일 때, arr.slice() 메서드나 [...arr] 배열 전개 연산자를 사용하면 된다.
    const o = { x: {y:1}};
    const c1 = {...o};
    console.log(o); // { x: {y:1}}
    console.log(c1); // { x: {y:1}}
    console.log(o===c1); // false

    console.log(o.x) // {y:1}
    console.log(c1.x) // {y:1}
    console.log(o.x === c1.x) // true

(1) o를 스프레드로 얕은 복사한 c1과 o는 { x: {y:1}}로 같지만, 서로 다른 별개의 객체이므로 일치하지 않는다. 
일치연산자 ===는 값, 타입, 객체까지 모두 같아야지만 true를 반환하는 엄격한 연산자이기 때문이다.
데이터 타입의 비교까지는 통과하더라도 o와 c1은 서로 다른 객체를 참조하고 있기 때문에 false다. 

(2) 변수 o의 x 프로퍼티 값과 변수 c1의 x 프로퍼티 값을 비교해보면 일치한다.
프로퍼티 값이란 객체의 속성(프로퍼티)에 할당된 값으로, 각각 {y:1}다.

    o.x = {z:1};
    console.log(o.x); // {z:1}
    console.log(c1.x); // {y:1}
    console.log(o.x === c1.x) // false

(3) 물론 o의 프로퍼티 x의 값을 갱신하면 다시 일치하지 않게 된다. 

 

11.2.2 깊은 복사 (Deep Copy)

  • 원본 객체, 배열의 내부에 있는 모두 객체, 배열을 재귀적으로 복사한다.
  • 재귀적(Recursive)이란, 함수나 알고리즘이 자기 자신을 호출하는 것을 말한다.
    즉, 객체나 배열의 내부 요소를 확인하고, 객체면 객체를 복사 / 배열이면 배열을 복사해서 새로운 객체/배열을 생성한다.
  • 복사본(객체, 배열)과 원본(객체,배열)의 구조는 서로 독립적이다. 즉, 복사본을 수정해도 원본에 영향을 주지 않는다.
  •  터미널에 "npm install lodash"을 입력해서 모듈을 설치한 뒤, lodash의 cloneDeep 함수를 사용해서 깊은복사를 해볼 수 있다. 
 
    const _ = require('lodash');

    const obj = { x: { y: 1 } };
    const copy = _.cloneDeep(obj);

    obj.x.y = 2;

    console.log(obj.x.y); // 2   
    console.log(copy.x.y);   // 1 (깊은 복사라서 원본 수정이 안된다.)