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

JH Cho·2022년 12월 12일
0

모던JS DeepDive 공부

목록 보기
11/27
post-thumbnail

모던 JS 딥다이브 공부 정리용 글입니다.

11_ 원시값과 객체의 비교

  • JS는 원시타입과 객체타입으로 구분할 수 있다.
  • 원시 타입의 값은 변경 불가능한 값이다 <-> 객체 타입의 값은 변경 가능한 값이다.
  • 원시값을 변수에 할당하면 변수(확보된 메모리 공간)에는 실제 값이 저장
  • 객체를 변수에 할당하면 변수에는 참조값이 저장
  • 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달(pass by value)
  • 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달(pass by reference)

11.1_ 원시 값

11.1.1_ 변경 불가능한 값(Immutable)

  • 한 번 생성된 값은 읽기 전용(read only) 값으로서 변경 불가
  • 변경 불가능 하다는 것은 변수가 아니라 값에 대한 진술이다.
  • 변수는 언제든지 재할당을 통해서 값을 변경할 수 있고 값 그자체가 변경 불가라는 뜻.

4장 5절 재할당

  • 원시 값을 할당한 변수에 원시 값을 재할당하면
    이전 원시 값을 변경하는 것이 아닌 새로운 메모리 공간을 확보하고
    재할당한 원시 값을 저장한 후 새롭게 재할당한 원시 값을 가리킨다.
    -> 결국 변수가 참조하던 메모리 공간의 주소가 바뀌는 것이다.
  • 이유 : 변수가 참조하던 메모리 공간의 주소가 변경된 이유는 할당된 원시 값이 변경 불가능한 값이기 때문.
  • 결론 : 불변성을 갖는 원시 값을 할당한 변수는 재할당 외에는 변수 값을 변경할 방법이 없다.

11.1.2_ 문자열과 불변성

  • 문자열은 다른 원시 값과 비교할 때 독특한 특징이 있다.
  • 문자열은 1개의 문자 당 2바이트의 메모리 공간에 저장된다
  • 숫자는 1이든 10000이든 동일한 8바이트가 필요하다.
  • JS는 개발자의 편의를 위해 원시 타입인 문자열을 제공한다.
  • JS의 문자열은 원시타입이며 변경 불가능하다.
var str = 'Hello';
str = 'world';
  • str은 'Hello'가 저장된 메모리를 가리키고 있다가
  • 'world'를 가리키도록 변경됐다.
  • 문자열은 유사 배열 객체!
  • 유사 배열 객체란 마치 배열처럼 인덱스로 프로퍼티 값에 접근 가능하고 length 프로퍼티를 갖는 객체이다. 인덱스와 length 프로퍼티가 있기에 for문으로 순회도 가능하다.
  • 문자열은 유사배열객체이며 이터러블(반복가능한)이다.
  • 하지만 문자열 일부를 변경할 수 없다. 문자열은 변경 불가한 값이니까
var str = 'string';

str[0] = 'S';
console.log(str) // string

11.1.3_ 값에 의한 전달

var score = 80;
var copy = score; // 레퍼런스가 아닌 값이 할당된 것.

score = 100;

console.log(score, copy) // 100, 80
  • score의 80과 copy의 80은 서로 다른 메모리에 저장된 별개의 값이다.

  • JS에는 사실 값에 의한 전달이란 용어가 없다. 결국 레퍼런스가 할당된 것이기 때문. 정확히 알고 싶으면 (144p~ 146p) 보자.

11.2_ 객체

  • 객체는 프로퍼티 개수가 정해져 있지 않다.
  • 프로퍼티 값도 제약이 없다
  • 고로 원시값처럼 확보해야할 메모리 공간의 크기를 사전에 정의할 수 없다.
  • 그래서 객체는 원시값과 다른 방식으로 동작하도록 설계되어 있다.

11.2.1_ 변경 가능한 값

  • 객체 타입의 값, 즉 객체는 변경 가능한 값이다.
  • 원시값은 해당 메모리에 값이 저장되어 있지만
  • 객체는 메모리에 객체의 실제 주소가 저장되어 있다.
//gㅏㄹ당되는 시점에 객체 리터럴이 해석되며 객체가 생성됨
var person = {
  name: 'Lee'
}

console.log(person.name)
// person변수에 저장된 참조 값으로 실제 객체에 접근.
  • 객체는 변경가능한 값으로서 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다.

👎 단점!!

  • 여러 개의 식별자가 하나의 객체를 공유해버리게 됨!

😽 Shallow & Deep copy

  • 얕은 복사는 한 단계까지만 복사
    const o = {x:{y:1}};
    //얕은 복사
    const c1 = {...o}
    console.log(c1 === o) // false
    //전개연산자로 레퍼런스가 아닌 새로운 객체의 주소가 할당되었기 때문.
    console.log(c1.x === o.x) // true

// npm install lodash(deep copy위한 모듈)
const _ = require('lodash');

const c2 = _.cloneDeep(o);
console.log(c2 === o) //false
console.log(c2.x === o.x) //false
상위, 하위 객체 모두 복사해버림.//둘 다 새로운 객체 레퍼런스가 부여됐단 말임.

  • 참고) 다른 의미로 원시 값을 다른 변수에 할당하는 것을 깊은 복사, 객체를 다른 변수에 할당하는 것을 얕은 복사라고 하기도 함.

11.2.2_ 참조에 의한 전달

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

  • 이 때 원본 변수와 복사 변수와 바인딩된 메모리 주소는 다르지만 메모리에 저장된 레퍼런스 주소는 동일하다.

  • 그래서 두 개의 식별자가 하나의 객체를 공유하게 된다.

  • 값에 의한 전달과 참조에 의한 전달은 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 면에서 동일하다.

  • 결국 JS에는 참조에 의한 전달은 존재하지 않고 값에 의한 전달만이 존재한다고 볼 수 있다.

마무리 문제

var person1 = {
  name: "Lee"
};

var person2 = {
  name: "Lee"
}

console.log(person1 === person2) // false
console.log(person1.name === person2.name)// true
  • 서로 다른 객체이다.
  • 하지만 person.name은 값으로 평가될 수 있는 표현식으로 두 표현식 모두 원시 값 'Lee'로 평가되어 같다.
profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글