[JS Deep Dive] 11장. 원시값과 객체의 비교

lyshine·2023년 3월 31일
0

JS Deep Dive 정리

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

✅ 원시 값

변경 불가능한 값

  • 원시 값은 변경 불가능한값이다. (immutable value)
  • 변경 불가능하다는 것은 변수가 아니라 값에 대한 말이다. 원시값을 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것은 아니다. (변수는재할당으로 언제든지 변수값 변경(교체) 가능)
  • 이러한 변경불가능한 특성은데이터의 신뢰성 보장
  • 원시값 재할당시 이전 원시값 변경이 아닌 새로운 메모리 공간을 확보해 재할당한 원시값을 저장하고 변수는 새로 재할당한 원시값을 가리킨다. (변수가 참조하던 메모리 공간의 주소는 바뀐다.)
  • 불변성을 갖는 원시값을 할당한 변수는 재할당 이외에 변수값을 변경할 수 잇는 방법이 없다.

문자열과 불변성

  • 원시값을 저장하려면 먼저 메모리 공간 크기를 확보해야 한다.
    • 원시 타입별로 메모리 공간의 크기가 다름
    • 문자열 타입(2바이트), 숫자타입(8바이트)…
  • 원시값인 문자열은 다른 원시값과 다른 독특한 특징이 있다.
    • 문자열은 몇 개의 문자로 이뤄졌느냐에 따라 필요한 메모리 공간의 크기가 결정된다. (숫자는 모두 동일한 8바이트지만 문자는 1개가 2바이트)
    • 문자열은 유사 배열 객체이면서 이터러블이므로 배열과 유사하게 각 문자에 접근할 수 있다.

값에 의한 전달

var score = 80;
var copy = score;
//두가지 평가방식 가능
//1. 새로운 80을 생성(복사)해서 메모리 주소를 전달하는 방식(할당시점에 두 변수가 기억하는 메모리 주소 다름)
//2. score 변수값80의 메모리 주소를 그대로 전달하는 방식(할당시점에 두 변수가 기억하는 메모리 주소 같음)

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

score = 100;

console.log(score);//100
console.log(copy);//80
console.log(score === copy) //false
  • 변수에 원시값을 갖는 변수를 할당하면 할당받는 변수(copy)에는 할당되는 변수(score)의 원시값이 복사되어 전달된다. ⇒ 값에 의한 전달
var score = 80;
var copy = score;

console.log(score);//80
console.log(copy); //80
console.log(score === copy) //true
// score변수와 copy변수의 값은 80으로 동일하지만 다른 메모리 공간에 저장된 별개의 값이다. 
// ⇒ score의 값을 변경해도 copy변수의 값에는 영향이 가지 않는다.
  • 다른 할당 방법2 : 변수에 원시값을 갖는 변수를 할당하는 시점에는 두 변수가 같은 원시값을 참조하다가 어느 한쪽의 변수에 재할당이 이루어졌을때 새로운 메모리 공간에 재할당된 값을 저장하도록 동작할 수도 있다.

  • “값에 의한 전달”이라는 용어를 썼지만,
    엄격하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달된다. 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있다. (단, 전달된 메모리 주소를 통해 메모리 공간에 접근하면 값을 참조할 수 있다.)

  • 변수에 원시값을 갖는 변수를 할당하면 결국 두 변수의 원시값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 할쪽에서 재할당을 통해 값을 변경해도 서로 간섭할 수 없다.

✅ 객체

  • 객체는 프로퍼티의 개수가 정해져 있지 않고 동적으로 추가/삭제가 가능하다. ⇒ 객체는 원시값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해둘 수 없다.
  • 복합적인 자료구조로 객체를 관리하는 방식이 원시값과 비교해 복잡하고 비용이 많이 든다.

변경 가능한 값

  • 객체(참조)타입의 값, 즉 객체는 변경 가능한 값이다.(mutable value)
  • 원시값(원시값을 할당한 변수는 원시값 자체를 값으로 가짐)과 달리,
    객체를 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 “참조 값”에 접근 가능하다.
  • 참조 값은 생성된 객체가 저장된 “메모리 공간의 주소”이다.
  • 변수는 이 참조값을 통해 객체에 접근할 수 있다.
  • 원시값과 다른 표현 방식
    • 원시값을 할당한 변수 : “변수는 ~값을 갖는다. 변수의 값은 ~다.”
    • 객체를 할당한 변수 : “변수는 객체를 참조하고 있다. 변수는 객체를 가리키고(point) 있다.”
  • 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다. (동적으로 프로퍼티 추가/수정/삭제 가능)
    이때, 객체를 할당한 변수에 재할당을 하지 않았으므로 객체를 할당한 변수의 참조값(메모리 주소)은 변경되지 않는다.
var person = {
	name : 'Lee'
};
person.name = 'Kim';//프로퍼티 값 갱신(수정)
person.address = 'Seoul';//프로퍼티 동적 생성
  • 메모리를 효율적으로 사용하고 비용을 절약하여 성능을 향상시키기 위해 객체는 변경 가능한 값으로 설계되었다.
  • 구조적 단점도 존재한다. 원시값과 다르게 여러개의 식별자가 하나의 객체를 공유할 수 있다.

참조에 의한 전달

  • 객체를 가리키는 변수(person)를 다른 변수(copy)에 할당하면 원본의 참조값이 복사되어 전달된다. 이를 “참조에 의한 전달”이라 한다.
    • 원본의 참조값을 복사해서 copy에 저장한다. 원본과 사본의 저장된 메모리 주소는 다르지만 동일한 참조 값을 갖는다.(동일한 객체를 가르키게 된다.) ⇒ 다른 두개의 식별자가 하나의 객체를 공유하게 된다.
    • 이때 둘중 한쪽에서 프로퍼티 값을 변경하면 서로 영향을 받게된다.
var person = {
	name : 'Lee'
}

//참조값을 복사(얕은 복사)
var copy = person;
console.log(copy === person); //true //두개의 변수는 동일한 객체를 가리킨다.

copy.name = 'Kim';
person.address = 'Seoul';

// 얕은 복사로 서로 영향을 주고받는다.
console.log(person); //{name:"Kim", address:"Seoul"}
console.log(copy); //{name:"Kim", address:"Seoul"}
  • 값에 의한 전달과 참조에 의한 전달은 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 점에서는 동일하다. 변수에 저장된 값이 원시값이냐 참조값이냐의 차이일뿐이다. ⇒ js에서 “참조에 의한 전달”은 존재하지 않고 “값에 의한 전달”만이 존재할뿐인 것
  • === 일치 비교 연산자를 통해 객체를 할당한 변수를 비교하면 참조값을 비교하게 된다.(원시값은 원시값 비교)
    • 서로 다른 객체가 내용은 같지만 가리키는 참조값이 다르면 false이다.

    • 원시 값을 할당한 객체의 프로퍼티를 비교하면 값 자체를 비교한다.

      var person1 = { name : 'Lee' }
      var person2 = { name : 'Lee' }
      
      console.log(person1 === person2); //false
      console.log(person1.name === person2.name); //true 

0개의 댓글