모던 자바스크립트 Deep Dive_원시 값과 객체의 비교

최현호·2022년 8월 21일
0

JavaScript

목록 보기
36/38
post-thumbnail

11_원시 값과 객체의 비교

자바스크립트에서 제공하는 데이터 타입은
크게 원시 타입(premitive type)객체 타입(obejct/reperence type) 으로 구분 하는데, 둘 사이는 차이점이 존재한다.

  • 원시 타입 값은 변경 불가능 한 값 이고,
    객체(참조) 타입 값은 변경 가능한 값 이다.
  • 원시 타입 값을 변수에 할당하면 변수(확보된 메모리 공간) 에는 실제 값이 저장
    객체(참조) 타입 값은 변수(확보된 메모리 공간)에는 참조 값이 저장
  • 원시 타입 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달
    객체 타입 값을 갖는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달

11.1 원시 타입 값

11.1.1 변경 불가능한 값

원시 타입은
변경 불가능한 값으로 읽기 전용(read only) 값이다.

JavaScript에서 원시 값(primitive, 또는 원시 자료형)이란 객체가 아니면서 메서드도 가지지 않는 데이터입니다. 원시 값에는 7종류, string, number (en-US), bigint (en-US), boolean, undefined, symbol, 그리고 null이 존재합니다.
( 출처 : MDN )

  • 원시 값 자체를 변경 불가능하다는 것이지, 변수 값을 변경 할 수 없다는 것이 아님을 유의!
// const 키워드를 사용 해 선언한 변수는 재할당이 금지된다. 상수는 재할당이 금지된 변수일 뿐이다.
const o = {};

// const 키워드를 사용해 선언한 변수에 할당한 원시 값(상수)은 변경할 수 없다.
// 하지만 const 키워드를 사용해 선언한 변수에 할당한 객체는 변경할 수 있다.
o.a = 1;
console.log(o); // {a: 1}

원시 값을 할당한 변수에 새로운 원시 값을 재할당 하면,

  • 메모리 공간에 저장되어 있는 재할당 이전의 원시 값을 변경하는 것이 아니라,
  • 새로운 메모리 공간을 확보 하고 재할당한 원시 값을 저장한 후,
    -> 변수가 참조하던 메모리 공간의 주소가 변경된 이유는, 변수에 할당된 원시 값이 변경 불가능한 값이기 때문
  • 변수는 새롭게 재할당한 원시 값을 가리킨다.
    -> 이러한 특성을 불변성이라고 한다
    -> 불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 값을 변경 할 수 있는 방법이 없다.

11.1.2 문자열과 불변성

문자열은
유사 배열 객체로서 배열과 유사하게 각 문장에 접근 할 수 있으나,
변경 불가능 한 값 이기 때문에 일부 문자를 변경해도 반영되지 않는다.
원시 타입은 문자열은 읽기 전용 이기 때문이다.

원시 값을 저장하려면 먼저 확보해야 하는 메모리 공간의 크기를 결정해야 한다.

  • 이를 위해 원시 타입별로 메모리 공간의 크기가 미리 정해져 있다.
  • ECMAScript 사양에
    -> 문자열 타입(2바이트) 와 숫자 타입(8바이트)
  • 이외의 원시 타입은 크기를 명확히 규정하고 있지 않다.
var str = 'string';

// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
// 하지만 문자열은 원시값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = 's';

console.log(str); // string

11.1.3 값에 의한 전달

변수에 원시 값을 할당하면, 할당받는 변수에는 할당되는 변수의 원시 값이 복사되어 전달 된다.

var score = 90;
var copy = score;

console.log(score); // 90
console.log(copy);  // 90

score = 100

console.log(score); // 100
console.log(copy);  // 100

score 변수와 copy 변수는 숫자 값 100을 갖는다는 점에서는 동일하지만,
score 변수와 copy 변수의 값 100은 다른 메모리 공간에 저장된 별개의 값이다.

즉, 값에 의한 전달은 사실 값을 전달하는 것이 아니라 메모리 주소를 전달한다.

중요한 것은
변수에 원시 값을 갖는 변수를 할당하면, ( 위와 같이 )
변수 할당 시점 이든, 두 변수 중 어느 하나의 변수에 값을 재할당 하는 시점 이든
두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값 이 되어
어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다.


11.2 객체

  • 프로퍼티의 개수가 정해져 있지 않아 동적으로 추가되고 삭제할 수 있고
  • 프로퍼티의 값에도 제약이 없다.
  • 원시 값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해 둘 수 없고
    복합적인 자료구조라서 ,원시 값과는 다른 방식으로 동작하도록 설계되어 있다.
  • 객체를 변경할 때 마다 복사해서 생성 후 변경하면 비용이 많이 든다.
  • 원시 값처럼 이전 값을 복사해서 새롭개 생성한다면
    -> 명확하고 신뢰성이 확보되겠지만
    -> 객체는 크기가 매우 클 수도 있고
    -> 원시 값처럼 크기가 일정하지도 않으며,
    -> 프로퍼티 값이 객체일 수도 있어서

따라서 메모리를 효율적으로 사용하기 위해,
그리고 객체를 복사해 생성하는 비용을 절약하여 성능을 향상시키기 위해
-> 객체는 변경 가능한 값으로 설계되어 있다.

11.2.1 변경 가능한 값

객체(참조) 타입의 값은 변경 가능한 값 이다.

  • 객체를 할당한 변수는 재할당 없이 객체를 직접 변경 할 수 있다.
  • 즉, 재할당 없이 프로퍼티를 동적으로 추가 할 수 있고
  • 값을 갱신 할 수 있으며, 자체를 삭제 할 수 있다.

얕은 복사와 깊은 복사

객체를 프로퍼티 값으로 갖는 객체인 경우

  • 얕은 복사한 단계 까지만 복사하는 것을 말하고 ➔ 참조 값을 복사
  • 깊은 복사객체에 중첩되어 있는 객체 까지 복사하는 것을 말한다.
    ➔ 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전한 복사본을 만드는 복사
const o = { x: { y: 1 } };

// 얕은 복사
const c1 = { ...o };       // 스프레드 문법
console.log(c1 === o);     // false
console.log(c1.x === o.x); // true

// lodash의 cloneDeep을 사용한 깊은 복사
// "npm install lodash"로 lodash를 설치한 후, Node.js 환경에서 실행
const _ = require('lodash');
// 깊은 복사
const c2 = _.cloneDeep(o);
console.log(c2 === o);     // false
console.log(c2.x === o.x); // false

const v = 1;

// "깊은 복사"라고 부르기도 한다.
const c1 = v;
console.log(c1 === v);     // true

const o = { x: 1 };

// "얕은 복사"라고 부르기도 한다.
const c2 = o;
console.log(c2 === o);     // true

얕은 복사와 깊은 복사로 생성한 객체는 원본과는 다른 객체다.
-> 원본과 복사본은 참조 값이 다른 별개의 객체다.


11.2.2 참조에 의한 전달

객체를 가리키는 변수(원본 person) 을 다른 변수(사본 copy)에 할당하면,
원본의 참조 값이 복사되어 전달 되는 것

var person = {
  name: 'Lee'
};

// 참조값을 복사(얕은 복사)
var copy = person;

위의 코드에서 person과 copy 모두 동일한 객체를 가리키는데
이는 두 개의 식별자가 하나의 객체를 공유 한다는것을 의미한다.


정리

값에 의한 전달참조에 의한 전달

  • 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 면에서 동일하지만,
  • 식별자가 기억하는 메모리 공간(변수)에 저장되어 있는 값이 원시 값이냐 참조 값이냐에 차이가 있다.
profile
현재 블로그 : https://choi-hyunho.com/

0개의 댓글