[딥다이브] 16장 프로퍼티 어트리뷰트, 17장 생성자 함수에 의한 객체 생성

주니·2023년 4월 9일
0

딥다이브

목록 보기
9/20

16. 프로퍼티 어트리뷰트

내부 슬롯과 내부 메서드

  • 자바 스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드.
  • 이중 대괄호 ([[…]])로 감싼 이름들.
  • 자바스크립트 내부 로직이므로 원칙적으로는 직접적으로 접근하거나 호출할 수 있는 방법을 제공하지 않는다.
  • 단, 일부에 한하여 간접적으로 접근할 수 있는 수단을 제공하기는 한다. ex)[[Prototype]] __proto__를 통해 접근 가능하다.

프로퍼티 어트리뷰트와 디스크립터 객체

  • 자바스크립트 엔진은 프로퍼티를 생성할 때 그 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다.
  • 프로퍼티 값[[value]], 값의 갱신 가능 여부[[writable]], 열거 가능 여부[[enumerable]], 재정의 가능 여부[[configurable]]
  • 직접적인 접근은 불가능하지만 간접적인 확인은 가능하다.
  • Object.getOwnPropertyDescriptor 메서드로 반환되는 값을 프로퍼티 디스크립터 객체라 한다.
const person = {
	name: 'Lee'
};

// 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환한다.
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// {value: "Lee", writable: true, enumerable: true, configurable: true}

데이터 프로퍼티와 접근자 프로퍼티

데이터 프로퍼티
키와 값으로 구성된 일반적인 프로퍼티. 지금까지 살펴본 모든 프로퍼티이다.

접근자 프로퍼티

  • 자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
  • getter/setter 함수라고도 부른다.

프로퍼티 정의

  • 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것.
  • Object.defineProperty , Object.defineProperties 메서드로 정의 가능

객체 변경 방지

객체는 변경 가능한 값이므로 재할당 없이 직접 변경할 수 있다. 추가, 삭제, 갱신 및 재정의 가능. 이를 막기 위한 다양한 메서드를 제공한다.

  • 객체 확장 금지 Object.preventExtensions . 추가금지
  • 객체 밀봉 Object.seal .읽기와 쓰기만 가능
  • 객체 동결 Object.freeze.읽기만 가능
  • 확장이 가능한 객체인지 여부를 Object.isExtensible 메서드로 확인 가능.

불변 객체

위의 변경 방지 메서드들은 얕은 변경 방지(shallow only)이다. 직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 주지 못한다.

읽기 전용의 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출해야 한다.

function deepFreeze(target) {
	if (target && typeof target === 'object' && !Object.isfrozen(target)) {
		Object.freeze(target);
		Object.keys(target).forEach(key => deepFreeze(target[key]));
	}
	return target;
}

17. 생성자 함수에 의한 객체 생성

Object 생성자 함수

new 연산자와 함께 object 생성사 함수를 호출 const person = new Object(); 생성된 객체를 인스턴스라 한다.

반드시 생성자 함수를 사용해 빈 객체를 생성해야 하는 것은 아니다. 객체 리터럴을 사용하는 것이 더 간편하다. 특별한 이유가 없다면, 그다지 유용해 보이지 않는다??

생성자 함수

  • 객체 리터럴의 단점: 단 하나의 객체만 생성한다. 여러 개 생성 시 비효율적이다.
  • 생성자 함수에 의한 객체 생성 방식의 장점: 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다.
  • 생성자 함수 내부에서 명시적으로 this가 아닌 다른 값을 반환하는 것은 생성자 함수의 기본 동작을 훼손한다. 따하서 return문을 반드시 생략해야 한다.

바인딩

식별자와 값을 연결하는 과정을 의미한다. 변수 선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩 하는 것이다. this 바인딩은 this와 this가 가리킬 객체를 바인딩 하는 것이다.

내부 메서드 [[Call]]과 [[Construct]]

  • 일반 객체는 호출할 수 없지만 함수는 호출할 수 있다. → 함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내붑 메서드는 물론, 함수로서 동작하기 위해 함수 객체만을 위한 [[Environment]], [[FormalParameters]] 등의 내부 슬롯과 [[Call]], [[Construct]] 같은 내부 메서드를 추가로 가지고 있다.

  • 내부 메서드 [[Call]]을 갖는 함수 객체를 callable ⇒ 호출할 수 있는 객체 즉 함수

  • 내부 메서드 [[Construct]]을 갖는 함수 객체를 constructor ⇒ 생성자 함수로서 호출할 수 있는 함수

constructor와 non-constructor의 구분

함수 정의 방식에 따라 구분

  • constructor : 함수 선언문, 함수 표현식, 클래스(클래스도 함수다)
  • non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수

일반 함수와 생성자 함수에 특별한 형식적 차이는 없다. 따라서 생성자 함수는 일반적으로 첫 문자를 대문자로 기술하는 파스칼 케이스로 명명하여 일반 함수와 구별할 수 있도록 하자!

new.target

  • this와 유사하게 constructor인 모든 함수 내부에서 암묵적인 지역 변수와 같이 사용되며 메타 프로퍼티라고 부른다.
  • new 연산자와 함께 생성자 함수로서 호출되었는지 확인할 수 있다.
  • 함수 내부의 new.target은 함수 자신을 가리킨다.
  • new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target은 undefined이다.
  • Object와 Function 생성자 함수는 new 연산자 없이 호출해도 new 연산자와 함께 호출했을 때와 동일하게 동작한다.
  • 하지만 String, Number, Boolean 함수는 new 없이 호출하면 타입만을 변환시킨다. - 명시적 타입 변환

0개의 댓글