원시 값과 객체의 비교

Published2024.04.26
Read Time11 min read

원시 값과 객체의 비교

원시 타입 vs 객체 타입

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

원시 값

원시 값: 원시 타입의 값, 원시 값은 변경 불가능한 값(읽기 전용의 값(readonly))

❗ 변수와 값은 엄연히 다른것!

  • 변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름
  • 은 변수에 저장된 데이터 표현식이 평가되어 생성된 결과
  • 변경 불가능한 것은 값에 대한 진술, 변수는 재할당을 통해, 변수 값을 변경(교체) 가능

** 변수vs상수 **

  • 변수는 언제든지 재할당을 통해 변수 값을 변경(교체)할 수 있다. 그래서 "변수"다.
  • 상수도 값을 저장하기 위한 메모리 공간이 필요하므로 변수라고 할 수 있다.
  • 하지만, 상수는 단 한 번만 할당이 허용하므로 변수 값을 변경할 수 없다. (이를 변경 불가능한 값으로 동일시하면 안됨 상수는 재할당이 금지된 변수)

불변성

변경 불가능한 값인 원시 값은 값을 변경하는 것이 아닌, 변수 값을 변경하기 위해 원시 값을 재할당하면 새로운 메모리 공간을 확보하고 재할당한 값을 저장한 후, 변수가 참조하던 메모리 공간의 주소를 변경한다. 값의 이러한 특성을 불변성 이라고 한다.

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

문자열과 불변성

자바스크립트는 개발자의 편의를 위해 문자열 타입을 원시 타입으로 제공한다.

문자열은 유사 배열객체이면서 이터러블이므로 배열과 유사하게 각 문자에 접근할 수 있다.

유사 배열 객체란?

  • 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있으며, length 프로퍼티를 갖는 객체
  • length 프로퍼티를 갖기 때문에 유사 배열 객체 이며, for 문으로 순회도 할 수 있다.
    var str = 'string';
    // 유사배열이므로, 배열과 유사하게 인덱스를 사용해 각 문자로 접근
    console.log(str[0]);
    // 원시 값인 문자열이 객체처럼 동작
    console.log(str.length); //6
    console.log(str.toUpperCase()); //STRING
    
var str = 'string'
// 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근
// 하지만 문자열은 원시 값이므로 변경할 수 없다. 이때 에러는 발생 x
str[0] = 'S'
console.log(str)// string

이는 데이터의 신뢰성을 보장한다. 변수에 새로운 문자열을 재할당하는 것은 물론 가능

값에 의한 전달

var score = 80;
var copy = score;

score = 100;

console.log(score); // 100 (원본 값)
console.log(copy); // 80  (복사한 값)

score는 변수 값 80으로 평가 되므로, copy 변수에도 80이 할당된다. 이때 새로운 숫자 값 80이 생성되어 copy변수에 할당된다

변수(copy)에는 할당되는 변수(score)의 원시 값이 복사되어 전달된다. 이를, 값에 의한 전달이라고 한다.

copy와 score는 별개의 값으로써, 서로의 변수의 값에 어떠한 영향도 주지않음.

또한, 엄격하게 말하자면, 변수에는 값이 전달되는 것이 아니라, 메모리 주소가 전달되는 것이다. 이는 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하기 때문이다.

이처럼 "값에 의한 전달"도 사실은 값을 전달하는 것이 아니라, 메모리 주소를 전달한다. 단, 전달된 메모리 주소를 통해 메모리 공간에 접근하면 값을 참조할 수 있다.

하지만 중요한 것은,

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

객체

자바스크립트는 다른 객체지향 언어와는 달리, 클래스 없이 객체 생성가능하며, 객체가 생성된 이후라도 동적으로 프로퍼티와 메서드 추가가 가능하다. V8 엔진에서는 히든 클래스라는 방식을 사용한다.

변경 가능한 값

객체(참조)타입의 값, 즉 객체는 변경 가능한 값

원시 값과 다르게, 객체를 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 참조 값에 접근한다!

  • 참조 값: 생성된 객체가 저장된 메모리 공간의 주소, 그 자체
var person = {
	name: 'Lee'
};

// person 변수에 저장되어 있는 참조 값으로 실제 객체에 접근한다.
console.log(person) //{name: "Lee"}

객체를 할당한 변수의 경우 "변수는 객체를 가리키고(참조하고)있다" 라고 표현한다. person 변수는 {name: 'Lee'}를 가리키고(참조하고) 있다. 객체를 할당한 변수는 원시 값과 달리, 재할당 없이 객체를 직접 변경할 수 있다. 즉, 재할당 없이 프로퍼티를 동적으로 추가, 프로퍼티 값을 갱신, 프로퍼티 자체를 삭제도 가능

var person = {
  name: "Lee",
};

// 프로퍼티 값 갱신
person.name = "Kim";

// 프로퍼티 값 동적 추가
person.address = "Seoul";

console.log(person); // { name: 'Kim', address: 'Seoul' }

원시 값과는 다르게 여러개의 식별자가 하나의 객체를 공유할 수 있다라는 부작용이 있다.

얕은 복사와 깊은 복사

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

  • 얕은 복사한단계만 복사하는 것을 말하며, 객체의 중첩되어있는 객체의 경우 참조 값을 복사한다.
  • 깊은 복사객체에 중첩되어 있는 객체까지 모두 복사하며, 원시 값처럼 완전한 복사본을 만든다.

참조에 의한 전달

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

person을 다른 변수(사본, copy)에 할당하면 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달 이라고 한다. 원본 person과 사본 copy는 동일한 참조 값을 가진다. 즉, 둘 모두 동일한 객체를 가리킨다. 이것은 두 개의 식별자가 하나의 객체를 공유한다는 것을 의미

var person = {
  name: "Lee",
};

// "참조 값"을 
복사, copy와 person이 동일한 참조 값을 갖는다.
var copy = person;
// 동일한 객체 참조하므로
console.log(copy === person); // true

// copy를 통해 객체의 name 프로퍼티를 변경한다.
copy.name = "Kim";

// person을 통해 객체의 address 프로퍼티를 동적 생성한다.
person.address = "Seoul";

// copy와 person은 동일한 객체를 가리키므로 서로 영향을 주고받음
console.log(person); // { name: 'Kim', address: 'Seoul' }
console.log(copy); // { name: 'Kim', address: 'Seoul' }

"값에 의한 전달"과 "참조에 의한 전달"은 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 전달한다는 면에서 동일하다. 따라서 "참조에 의한 전달"은 존재하지 않고 "값에 의한 전달"만이 존재한다고 할 수 있다.