자바스크립트 교과서 - 8. 객체

Seoyong Lee·2023년 10월 2일
0

개발 공부

목록 보기
10/21
post-thumbnail

객체의 특징

자바스크립트는 객체(object) 기반의 프로그래밍 언어이며, 자바스크립트를 구성하는 거의 “모든 것”이 객체다. 원시 값을 제외한 나머지 값(함수, 배열, 정규 표현식 등)은 모두 객체다.

이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p124.

  • 객체는 0개 이상의 프로퍼티로 구성된 집합으로 프로퍼티는 키(key)와 값(value)로 구성된다.
  • 프로퍼티 값이 함수인 경우 메서드(method)라 부른다.
const person = {
	name: 'lee', // 프로퍼티 키: name, 프로퍼티 값: 'lee'
	age: 32,
	sayHi() {
	  console.log("hi"); // 메서드
	}
}

원시 타입과 객체의 차이점

  • 자바스크립트는 7가지 원시 타입을 제외하면 모두 객체 타입으로 볼 수 있다.
  • 모던 자바스크립트 Deep Dive 11장에서 원시 타입과 객체 타입의 차이점을 다음과 같이 잘 설명하고 있다.
  • 원시 타입의 값, 즉 원시 값은 변경 불가능한 값(immutable value)이다. 이에 비해 객체(참조) 타입의 값, 즉 객체는 변경 가능한 값(mutable value)이다.
  • 원시 값을 변수에 할당하면 변수(확보된 메모리 공간)에는 실제 값이 저장된다. 이에 비해 객체를 변수에 할당하면 변수(확보된 메모리 공간)에는 참조 값이 저장된다.
  • 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달된다. 이를 값에 의한 전달(pass by value)이라 한다. 이에 비해 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달(pass by reference)이라 한다.

    이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p137.
  • 원시 타입은 각 타입에서 본 것과 같이 모두 변경이 불가능한 값이다. 한 번 생성된 원시 값은 읽기 전용으로 변경이 불가능하다.
    • 여기서 오해하면 안 되는 점은 변수는 얼마든지 변경할 수 있다. 다만 변수의 재할당이 원시 값 자체를 변경하는 것은 아니다. 변경이 불가능한 것은 ‘값에 대한 진술’이다

프로퍼티 어트리뷰트

  • 위에서 설명한 객체 내부의 프로퍼티는 사실 생성과 동시에 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다. 프로퍼티 어트리뷰트를 이해하기 위해서는 내부 슬롯과 내부 메서드에 대해 먼저 이해해야 한다.

내부 슬롯(internal slot)과 내부 메서드(internal method)는 ECMAScript 사양에 정의된 대로 구현되어 자바스크립트 엔진에서 실제로 동작하지만 개발자가 직접 접근할 수 있도록 외부로 공개된 객체의 프로퍼티는 아니다. …예를 들어, 모든 객체는 [[Prototype]]이라는 내부 슬롯을 갖는다. 내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 원칙적으로 직접 접근할 수 없지만 [[Prototype]] 내부 슬롯의 경우, __proto__를 통해 간접적으로 접근할 수 있다.

이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p220.

  • 즉, 프로퍼티 어트리뷰트는 자바스크립트 엔진이 관리하는 내부 상태 값인 내부 슬롯이다. Prototype과 마찬가지로 직접 접근이 불가능하지만 Object.getOwnPropertyDescriptor 메서드를 사용해 간접적으로 확인할 수 있다.

    const person = {
        name: 'lee'
    };
    
    console.log(Object.getOwnPropertyDescriptor(person, 'name'));
    // {value: "lee", writable: true, enumerable: true, configurable: true}
  • 프로퍼티는 다음 두 형태로 구분할 수 있다.

    • 데이터 프로퍼티(data property): 키와 값으로 구성된 일반적인 프로퍼티
      • 다음의 프로퍼티 어트리뷰트를 가진다.
        • [[Value]]: 키를 통해 값에 접근하면 반환되는 값
        • [[Writable]]: 값의 변경 여부(boolean)
        • [[Enumerable]]: 프로퍼티 열거 가능 여부(boolean)
        • [[Configurable]]: 프로퍼티 재정의 가능 여부(boolean)
    • 접근자 프로퍼티(accessor property): 다른 데이터 프로퍼티 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티
      • 다음의 프로퍼티 어트리뷰트를 가진다.
        • [[Get]]: 접근자 프로퍼티를 통해 데이터 프로퍼티 값을 읽을 때 호출되는 접근자 함수
        • [[Set]]: 접근자 프로퍼티를 통해 데이터 프로퍼티 값을 저장할 때 호출되는 접근자 함수
        • [[Enumerable]]: 프로퍼티 열거 가능 여부(boolean)
        • [[Configurable]]: 프로퍼티 재정의 가능 여부(boolean)
  • 각 프로퍼트 어트리뷰트에 대해 조금 더 자세히 알고 싶다면 You Don’t Know JS의 2번째 책 ‘this와 객체 프로토타입, 비동기와 성능’ 3장 객체 부분을 추천한다.


객체 변경 방지

  • 객체는 변경 가능한 값이므로 직접 변경이 가능하지만 이러한 변경을 방지하는 메서드도 존재한다.
    • Object.preventExtension 메서드는 객체의 확장(프로퍼티 추가)을 금지한다.
    • Object.seal 메서드는 객체를 밀봉한다. 밀봉(seal)이란 프로퍼티 추가 및 삭제, 프로퍼티 어트리뷰트 재정의 금지를 의미한다. 밀봉된 객체는 읽기와 쓰기만 가능하다.
    • Object.freeze 메서드는 객체를 동결한다. 동결(freeze)이란 프로퍼티 추가 및 삭제와 프로퍼티 어트리뷰트 재정의 금지, 프로퍼티 값 갱신 금지를 의미한다. 동결된 객체는 읽기만 가능하다.
  • 이러한 변경 방지 메서드는 얕은 변경 방지(shallow only)로 직속 프로퍼티만 변경되며 중첩 객체까지 영향을 주지는 못 한다.
    const person = {
    	name: 'Lee',
    	address: { city: 'Seoul' }
    };
    Object.freeze(person);
    console.log(Object.isFrozen(person)); // true
    console.log(Object.isFrozen(person.address)); // false

References

데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022)
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020)
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017)
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020)

0개의 댓글