[딥다이브] 프로퍼티, 생성자 함수

Dongs·2023년 3월 23일
0

[딥다이브]

목록 보기
7/11

내부 슬롯, 내부 메서드

  • [[]] 로 감싼 이름들이 모두 내부 슬롯과 내부 메서드이다.
  • 자바스크립트 엔진의 구현 알고리즘을 설명하기 위에 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드이다.
  • 모든 객체는 [[Prototype]] 이라는 내부 슬롯을 가진다.
const obj = {};

obj.__proto__ // 이렇게 간접적으로만 참조 가능.

위의 코드처럼 obj.[[Prototype]] 이렇게는 참조할 수 없고 __proto__로 간접적으로 참조할 수 있다.

프로퍼티 어트리뷰트

  • 프로퍼티 어트리뷰트는 프로퍼티의 상태를 나타내는 내부 슬롯이다.
  1. [[Value]] 프로퍼티 값
  2. [[Writable]] 프로퍼티 수정 여부
  3. [[Enumerable]] 열거 여부
  4. [[Configurable]] 재정의 여부
  • Default Boolean값은 true 이다.

프로퍼티 디스크립터 객체

  • 프로퍼티 어트리뷰트 정보를 제공하는 객체이며 위에서 언급했던 프로퍼티 어트리뷰트가 객체에 담겨 있다. 프로퍼티는 두 가지로 분류 된다.

데이터 프로퍼티

  • 키와 값으로 구성된 일반적인 프로퍼티다.

접근자 프로퍼티

  • 자체적으로 값을 갖지 않고 다른 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티이다.

접근자 프로퍼티의 어트리뷰트

  • 접근자 프로퍼티의 어트리뷰트는 다음과 같다.
  1. [[Get]] 프로퍼티 값을 읽어올 때 호출되는 접근자 함수(getter)
  2. [[Set]] 프로퍼티 값을 저장할 때 호출되는 접근자 함수(setter)
  3. [[Enumerable]] 열거 여부
  4. [[Configurable]] 재정의 여부

프로퍼티 정의

  • 프로퍼티와 어트리뷰트를 밑의 코드처럼 정의해줄 수도 있다.
const obj={};

Object.definedProperties(obj, {
	name: {
		value: 'afk',
      	writable: 'true',
      	enumerable: 'true',
      	configurable: 'true'
    }
}

객체 변경 방지

  • 프로퍼티 어트리뷰트를 재정의 할 수도 있지만 객체의 변경을 방지하는 다양한 메소드들이 있다. 너무 많다..
구분메소드추가삭제읽기쓰기재정의
객체 확장 금지Object.preventExtensionsXOOOO
객체 밀봉Object.sealXXOOX
객체 동결Object.freezeXXOXX
  • 객체 동결은 중첩 객체까지 영향을 주지 않는다. 따라서 별도의 작업이 필요하다!

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

생성자 함수란?

  • 생성자 함수는 new 연산자와 함께 인스턴스를 생성하는 함수를 말한다.

=> 붕어빵 틀과 같다고 생각하면 될 것같다. 붕어빵 틀이라는 생성자 함수가 있다하면 const 붕어빵1 = new 붕어빵틀() 하면 붕어빵 틀에 찍혀 만들어진 붕어빵1 이라는 인스턴스가 생긴다.

  • 객체는 프로퍼티를 통해 상태를 표현하고 메소드를 통해 동작을 표현한다.

this는 뭐를 가리킬까?

  • 일반함수로써 호출을 하였다면 this는 윈도우 전역객체를 가리킨다.
  • 메소드로써 호출을 하였다면 this는 메소드가 존재하는 객체를 가리킨다.
  • 생성자 함수로써 호출을 하였다면 this는 암묵적으로 생성자 함수가 생성할 인스턴스를 가리킨다.

생성자 함수의 인스턴스 생성 과정

  1. 인스턴스 생성 후 this 바인딩
const obj = new Circle();

위의 코드는 new 연산자를 사용해 obj 인스턴스를 생성했다.

  • 먼저 암묵적으로 빈 객체가 생성된다.

  • 그리고 이 빈 객체(인스턴스) 는 암묵적으로 this에 바인딩 된다.
    => 생성자 함수 내부의 this가 생성자 함수가 생성할 인스턴스를 가리키는 이유이다.

  • 이 작업은 런타임 이전에 이루어진다.

  1. 인스턴스 초기화
  • 생성자 함수에 있는 코드가 한 줄씩 실행되어 this에 바인딩 되어 있는 인스턴스를 초기화한다.
function Circle(name, str){
	this.name = name;
  	this.func = function(){
     return this.name + str; 
   }
}

위는 Circle이라는 생성자 함수이며 예를 들어 const obj = Circle("kim", "afk"); 이렇게 인스턴스를 생성했다하면 인수로 전달받은 초기값은 인스턴스 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다.

  1. 인스턴스 반환
  • 생성자 함수 내부의 모든 처리가 끝나면 인스턴스가 바인딩된 this가 암묵적으로 반환된다.

위에서 언급한 obj 인스턴스는 Circle {name: 'kim', func: f} 라는 프로퍼티 객체를 갖게 된다.

만약

function Circle(name, str){
	this.name = name;
  	this.func = function(){
     return this.name + str; 
   }
  
  return {};
}

const obj = new Circle(); // {}

명시적으로 객체 타입을 반환하면 마지막 return 문을 따른다. 따라서 obj는 빈 객체가 된다.

그러나 원시타입을 명시적으로 반환하면 정상적으로 인스턴스를 생성한다.

[[Call]] 과 [[Constructor]]

  • 함수는 객체이지만 일반 객체와 다르다. 제목의 내부 메소드를 추가로 가지고 있다.
  • 일반함수로써 호출되면 내부메서드 [[Call]]이 호출되고 new 연산자와 함께 생성자 함수로써 호출되면 내부메서드 [[Constructor]]가 호출 된다.
  • 내부메서드 [[Call]]을 갖는 함수 객체를 callbale 이라고 부른다.
  • 내부메서드 [[Constructor]]을 갖는 함수 객체를 constructor 이라고 부른다.
  • 내부메서드 [[Constructor]]을 갖지 않는 함수 객체를 non-constructor 이라고 부른다.

=> 예를 들어 arrow function 과 객체 메소드 축약형은 constructor 내부 메서드가 존재하지 않는다. 따라서 생성자 함수로 사용할 수 없으며 non-constructor라고 부른다.

profile
자대고 css 하는 프론트엔드 개발자

0개의 댓글