11장 원시 값과 객체의 비교

seo0·2023년 3월 1일
0

JavaScript

목록 보기
10/26
post-thumbnail

자바스크립트는 데이터 타입을 크게 원시 타입과 객체 타입으로 구분한다. 원시 타입과 객체 타입의 다른접은 크게 3가지 정도 있다.

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



원시값

변경 불가능한 값

원시 타입의 값, 즉 원시 값은 변경 불가능한 값이다.

원시값은 변경 불가능한 값이라는 말은 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 말이 아니다. 변수 값은 재할당을 통해 변경할 수 있다.

변수의 상대 개념인 상수는 재할당이 금지된 변수인데 이때 상수와 변경 불가능한 원시값을 동일시 하는것은 옳지 않다. 상수는 재할당이 금지된 변수일 뿐 원시값이 아니다.

원시값을 할당한 변수에 새로운 원시값을 재할당하게 되면 메모리 공간에 저장되어 있는 재할당 이전의 원시값을 변경하는 것이 아니라 새로운 메모리 공간을 확보하고 재할당할 원시값을 저장한 후, 변수가 재할당할 원시값을 가리키게 된다.
즉 변수가 참조하던 메모리 공간의 주소가 바뀌는 것이다.

변수가 참조하던 메모리 공간의 주소가 변경된 이유는 변수에 할당된 원시 값이 변경 불가능한 값이기 때문이다.

값의 이러한 특성을 불변성이라고 하며 불변성을 갖는 원시값을 할당한 변수는 재할당 이외에는 변수 값을 변경할 수 있는 방법이 없다.

문자열과 불변성

문자열은 다른 원시값과 다른 특징이 있다. 문자열은 0개 이상의 문자로 이루어진 집합이며 1개의 문자를 저장하는데 2바이트 메모리가 사용된다. 즉 1개의 문자로 이루어진 문자열은 2바이트, 5개의 문자로 이루어진 문자열은 10바이트가 필요하다.

var str1 = 'ㄱ';  //1개의 문자로 이루어진 문자열 -> 2바이트 필요
var str2 = 'hello'  //5개의 문자로 이루어진 문자열 -> 10바이트 필요

이러한 문자열은 유사 배열 객체이변서 이터러블이므로 배열과 유사하개 각 문자에 접근 가능하다.

여기서 유사 배열 객체란 마치 배열처럼 인덱스로 프로퍼티 값에 접근 가능하며, length 프로퍼티를 갖는 객체를 말한다. length 프로퍼티를 갖기 때문에 for문 순회도 가능하다.

var str = 'kim';
console.log(str[0]);  //k
console.log(str.length);  //3
console.log(str.toUpperCase());  //KIM

//하지만 문자열은 원시값이므로 값으 변경은 불가능하다.
str[0] = "p";
console.log(str);  //"kim"

값에 의한 전달

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

아래 예제로 살펴보면 copy = num에서 num은 변수 값 80으로 평가되므로 새로운 숫자값 80이 생성되어 copy변수에 할당되는 것이다.

var num = 80;
var copy = num;

console.log(num, copy);  //80 80
console.log(num === copy);  //true

변수 num과 copy는 숫자값 80을 갖는 점에서 동일하지만 서로 다른 메모리 공간에 저장된 별개의 값이다.

이때 변수 값을 평가하는 방식은 두가지가 있다.

  • 새로운 80을 생성해서 메모리 주소를 전달하는 방식
  • num의 변수값 80의 메모리 주소를 그대로 전달하는 방식

첫번째방식은 할당 시점에 두 변수가 기억하는 메모리 주소가 다르며, 두번째 방식은 할당 시점에 두 변수가 기억하는 메모리 주소가 같다. 하지만 둘 중 어느 방법을 사용하더라도 변수 할당 시점이든 변수에 값을 재할당 하는 시점이든 결국 두 변수의 원시값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경해도 서로 간섭할 수 없다는 점이다.


값에 의한 전달은 자바스크립트 용어가 아니라 헷갈릴수 있다. 자바스크립트에서 값에 의한 전달을 좀 더 정확하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달되는 것이다. 변수와 같은 식별자는 값이 아닌 메모리 주소를 기억하고 있기 때문이다.




객체

객체는 프로퍼티의 개수가 정해져있지 않고, 프로퍼티를 동적으로 추가/삭제할 수 있다. 또한 프로퍼티 값에 제약도 없다. 따라서 객체는 원시값 같이 확보해야할 메모리 공간의 크기를 사전에 정할 수 없다.

자바스크립트 객체는 프로퍼티 키를 인덱스로 사용하는 해시테이블이라고 생각할 수도 있으며 자바스크립트 엔진에서는 프로퍼티에 접근하기 위해 히든 클래스라는 방식을 사용해 접근한다.

변경 가능한 값

객체는 변경 가능한 값이다. 원시값을 할당한 변수를 참조하면 메모리에 저장되어 있는 원시값에 접근하게된다. 하지만 객체를 할당한 변수를 참조하면 참조값(변수가 기억하는 메모리 주소)를 통해 실제 객체에 접근하게 된다.
이때 참조값은 생성된 객체가 저장된 메모리 공간의 주소 그 자체이다.

일반적으로 원시값을 할당한 변수는 "변수는 oo값을 갖는다" 혹은 "변수 값은 o다." 라고 표현하고 객체를 할당한 변수의 경우 "변수는 객체를 참조하고있다." 혹은 "변수는 객체를 가리키고 있다."라고 표현한다.

var person = {
  name: 'kim'
};

console.log(person);  //{name: "kim"}

객체를 할당한 변수는 재할당 없이 객체를 직접 변경 가능하다. 즉 프로퍼티 값을 갱신하거나 동적 생성, 삭제할 수 있다.

var person = {
  name: 'kim'
};
//프로퍼티 값 갱신
person.name = 'park';
//프로퍼티 값 동적 생성
person.age = 24;

console.log(person);  //{name: "park", age; 24}

이때 객체를 할당한 변수에 재할당하는 것은 아니므로 객체를 할당한 변수의 참조값은 변경되지 않는다.

객체는 크기가 매우 클 수도 있고, 원시값처럼 크기가 일정하지 않으며, 프로퍼티 값이 객체일 수도 있어서 복사해서 생성하는 비용이 크기 때문에 재할당을 사용하지 않는다. 이러한 구조적 단점으로 인해 객체는 여러개의 식별자가 하나의 객체를 공유할 수 있다는 부작용이 있다.

참조에 의한 전달

객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조값이 복사되어 전달된다. 이를 참조에 의한 전달이라한다.

아래 예제로 살펴보면 원본 person을 사본 copy에 할당하면 원본의 참조값을 복사해서 copy에 전달하게된다.

var person  = {
  name: 'kim'
};

var copy = person;

person과 copy가 저장된 메모리 주소는 다르지만 동일한 참조값을 갖게 된다. 이것이 바로 두개의 식별자가 하나의 객체를 공유한다는 것을 의미한다. 따라서 원본 또는 사본 중에 어느 한쪽에서 객체를 변경하면 서로 영향을 주고 받는다.

var person  = {
  name: 'kim'
};
//copy와 person은 같은 참조값을 가짐
var copy = person;

console.log(copy === person);  //true

//객체 변경
copy.name = 'park';
person.age = 24;

console.log(person);  //{name: "park", age: 24}
console.log(copy);  //{name: "park", age: 24}

값에 의한 전달과 참조에 의한 전달은 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 면이 공통점이다. 하지만 식별자가 기억하는 메모리 공간인 변수에 저장되어있는 값이 원시값인지 참조값인지에 대한 차이만 있을 뿐이다.

결국 자바스크립트는 참조에 의한 전달은 존재하지 않고 값에 의한 전달만 존재한다고 할 수 있다.







📔출처
위키북스 - 모던 자바스크립트 Deep Dive
https://wikibook.co.kr/mjs/

0개의 댓글