JavaScript - 원시 값과 객체(참조)의 비교

Moolbum·2022년 1월 31일
0

JavaScript

목록 보기
11/18
post-thumbnail

원시타입과 객체타입

자바스크립트는 7가지 데이터 타입을 제공한다.
크게 원시타입, 객체타입으로 구분한다.

  • 원시타입(primitive type)
    • 숫자
    • 문자열
    • 불리언
    • null
    • undefined
    • 심벌

  • 객체타입(object/reference type)
    • 객체

원시 타입

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

객체 타입

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

원시 타입

1. 변경 불가능한 값

원시타입의 값은 변경 불가능한 값이다. 한번 생성된 원시 값은 읽기 전용 값으로 변경할 수 없다.
변경이 불가능 하다는 것은 변수가 아니라 값에 대한것이다.

원시 값은 변경 불가능한 값이기 때문에 값을 직접 변경 할 수 없다.
따라서 변수 값을 변경하기 위해 원시 값을 재할당하면

  • 새로운 메모리 공간을 확보
  • 재할당한 값을 저장
  • 변수가 참조하던 메모리 공간의 주소 변경

이러한 특성을 불변성 이라 한다.
재할당 이외에 원시 값인 변수 값이 변경된다면
상태 변경을 추적하기 어렵게 만든다.

불변성을 가지는 원시 값을 할당한 변수는 재할당 이외에 변수 값을 변경할 방법이 없다.

2. 문자열과 불변성

let str = 'Hello';
str = 'world';

문자열을 수정하는 것이 아니다.
새로운 문자열 world를 메모리에 생성하고 str은 이것을 가리키도록 변경
즉 문자열 Hello와 world는 모두 메모리에 존재하고 있다.
식별자 str은 문자열 Hello를 가리키다가 world를 가리키도록 변경

3. 값에 의한 전달

let score = 80;
let copy = score;
console.log(score === copy) // true 80 : 80

score = 100;
console.log(score === copy) // false 100 : 80

score 변수의 80과 copy의 80은 다른 메모리 공간에 저장된 별개의 값이다.
따라서 score 변수의 값을 변경해도 copy 변수의 값에는 영향을 주지 않는다.
두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한 곳에서
재할당을 통해 값은 변경하더라도 서로 간섭할 수 없다.


객체 타입

1. 변경 가능한 값

객체(참조) 타입의 값, 객체는 변경 가능한 값이다.
객체를 할당한 변수는 재할당 없이 객체를 직접 변경 할 수 있다.
프로퍼티를 추가, 갱신, 삭제 할 수 있다.

let person = {
    name: 'Lee'
};

console.log(person) // {name:'Lee'}

//프로퍼티 값 갱신, 동적생성
person.name = 'Kim';
person.address = 'Seoul';
console.log(person) // {name: 'Kim',address: 'Seoul'}

2. 얕은 복사, 깊은 복사

객체를 프로퍼티 값으로 갖는 객체의 경우 얕은복사는 한 단계까지만 복사를 하는 것, 깊은복사는 객체에 중첩되어있는 객체까지 모두 복사하는 것이다.

얕은 복사

참조 값을 복사해서 사용

const obj = { a: 1, b: 2};
const copyObj = obj;
console.log( obj === copyObj ) // true

깊은복사

  1. 스프레드 연산자사용 (...spread)
    depth 하나 일 때 사용 할 수 있는 깊은복사 방법이다.
const obj = { a: 1, b: 2};
const copyObj = {...obj};

copyObj.a = 10;
console.log( obj === copyObj ) // false
console.log( obj.a) // 1
console.log( copyObj.a ) // 10
  1. Object.assign() 메서드 사용
const obj = { a: 1, b: 2};
const copyObj = Object.assign({}, obj);

copyObj.a = 10;
console.log( obj === copyObj ) // false
console.log( obj.a) // 1
console.log( copyObj.a ) // 10

depth가 많은 객체의 경우는

  • lodash cloneDeep을 사용
  • JSON.stringify( )사용

3. 참조에 의한 전달

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

var person = {
  name: 'Lee'
};
// 참조 값을 복사 얕은복사
var copy = person

참조 값을 복사 했기 때문에
두 개의 식별자가 하나의 객체를 공유하고 있다.
어느 한 쪽에서 객체를 변경한다면 서로 영향을 주고 받습니다.

var person1 = {
   name:'Lee'
}
var person2 = {
   name:'Lee'
}

console.log(person1 === person2); //false
console.log(person1.name === person2.name); //true

person1 과 person2는 변수가 가리키는 내용은 같지만 다른 메모리에 저장된 별개의 객체다.
하지만 프로퍼티 값을 참조하는 두 표현식 모두 원시값 'Lee'로 평가된다.
따라서 비교하게 된다면 true를 가지게 된다.

profile
Junior Front-End Developer 👨‍💻

0개의 댓글