관리 메뉴

진취적 삶

17 생성자 함수에 의한 객체 생성 본문

개발 도서/자바스크립트 deepdive

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

hp0724 2023. 7. 11. 12:46

17.1 Object 생성자 함수

new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환 생성자 함수란 new 연산자와 함께 호출하여 객체를 생성하는 함수.

생성자 함수에 의해 생성된 객체를 인스턴스 라고 한다.

반드시 Object 생성자 함수를 사용해 빈 객체를 생성해야 하는것은 아니다.

특별한 이유가 없으면 그다지 유용해 보이지 않음

const strObj = new String("suha");
console.log(typeof strObj);
console.log(strObj);

const numObj = new Number(123);
console.log(typeof numObj);
console.log(numObj);

const boolObj = new Boolean(true);
console.log(typeof boolObj);
console.log(boolObj);

const func = new Function("x", "return x *x");
console.log(typeof func);
console.dir(func);

const arr = new Array(1, 2, 3);
console.log(typeof arr);
console.log(arr);

const regExp = new RegExp(/ab+c/i);
console.log(typeof regExp);
console.log(regExp);

const date = new Date();
console.log(typeof date);
console.log(date);

17.2 생성자 함수

17.2.1 객체 리터럴에 의한 객체 생성 방식의 문제점

객체 리터럴에 의한 객체 생성방식은 단 하나의 객체만 생성 동일한 프로퍼티 여러개 생성할경우 매번 프로퍼티를 기술해야함.

객체 리터럴에 의해 객체를 생성하는 경우 프로퍼티 구조가 동일함에도 불구하고 매번 같은 프로퍼티와 메서드를 기술해야 한다.

17.2.2 생성자 함수에 의한 객체 생성 방식의 장점

객체(인스턴스) 를 생성하기 위한 템플릿 (클래스) 처럼 생성자 함수를 사용하여

프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성

new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다 .

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);

console.log(circle1.getDiameter());
console.log(circle2.getDiameter());

this : 객체 자신의 프로퍼티나 메소드를 참조하기 위한 자기 참조 변수

this 바인딩은 함수 호출 방식에 따라 결정된다.

함수 호출 방식 this가 가리키는 값

일반 함수로서 호출 전역 객체
메서드로서 호출 메서드를 호출한 객체
생성자 함수로서 호출 생성자 함수가 생성할 인스턴스

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

생성자 함수의 역할은 프로퍼티 구조가 동일한 인스턴스를 생성하기 위한 템플릿으로서 동작

인스턴스를 생성하는것과 완성된 인스턴스를 초기화 하는것이다.

  1. 인스턴스 생성과 this 바인딩

암묵적으로 생성된 빈 객체 = 인스턴스는 this에 바인딩 된다. 이 처리는 함수 몸체의 코드가 한 줄씩 실행되는 런타임 이전에 실행된다.

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

```jsx
function Circle(radius) {
// 생성자 함수가 생성할 인스턴스 
  console.log(this);//Circle {}
  this.radius = radius; 
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

const circle1 = new Circle(5);
```
  1. 인스턴스 초기화
    function Circle(radius) {
        //1 암묵적으로 인스턴스가 생성 this에 바인딩
    
        //2 this에 바인딩되어 있는 인스턴스를 초기화 한다. 
      this.radius = radius;
      this.getDiameter = function () {
        return 2 * this.radius;
      };
    }
    
  2. 생성자 함수에 기술되어 있는 코드 this에 바인딩되어 있는 인스턴스 초기화
  3. 인스턴스 반환
  4. function Circle(radius) { //1 암묵적으로 인스턴스가 생성 this에 바인딩 //2 this에 바인딩되어 있는 인스턴스를 초기화 한다. this.radius = radius; this.getDiameter = function () { return 2 * this.radius; }; return 100; //3 완성된 인스턴스가 바인딩된 this 가 암묵적으로 반환 // 명시적으로 원시값을 반환하면 값 반환은 무시하고 암묵적으로 this 가 반환된다. } const circle = new Circle(1); console.log(circle); //Circle { radius: 1, getDiameter: [Function (anonymous)] }

17.2.4 내부 메서드 [call] 과 [ Construct]

일반 객체는 호출할수 없지만 함수는 호출할수 있다.

함수가 일반 함수로서 호출되면 함수 객체의 내부 메서드 call 이 호출되고

new 연산자와 함께 호출되면 내부 메서드 construct 가 호출

function foo () {}
//call
foo()
//construct  
new foo()

내부 메서드를 갖는 함수 객체를 callable (호출할수 있는 객체)

내부 메서드 construct 를 갖는 함수는 constructor (생성자 함수로서 호출할수 있는)

construct 를 갖지 않는 함수 객체를 non-constructor (객체를 생성자 함수로서 호출할수 없는)

호출할수 없는 객체는 함수 객체가 아니다 즉 함수 객체는 callable 하면서 construct 거나

callable 하면서 non -constructor 이다 .

17.2.5 constructor 와 non -constructor 구분

  • constructor : 함수 선언문 , 함수 표현식 ,클래스
  • non -constructor : 메서드 ,화살표 함수

17.2.6 new 연산자

new 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작

call 이 호출되는것이 아니라 construct 가 호출

new 연산자 없이 생성자 함수를 호출하면 일반 함수로 호출

construct가 호출되는것이 아니라 call 이 호출

17.2.7 new.target

함수 내부에서 new.target 을 사용하면 new 연산자와 함께 생성자 함수로서 호출되었는지 확인할수 있다. new 연산자와 함께 생성자 함수로서 호출되면 new.target 은 함수 자신을 가리킨다 .

new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target 은 undefined 다

//생성자 함수
function Circle(radius) {
  //이 함수가 new 연산자와 함께 호출되지 않으면 new.target 은 undefine이다
  if (!new.target) {
    return new Circle(radius);
  }
  //초기화
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
//new 연산자 없이 생성자 함수를 호출하여도 new.target 통해 생성자 함수로서 호출
const circle = Circle(5);
console.log(circle.getDiameter());

스코프 세이프 생성자 패턴 : new.target 을 사용할수 없는 상황이라면 사용하자

function Circle(radius) {
  if (!(this instanceof Circle)) {
    return new Circle(radius);
  }

  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

const circle = Circle(5);
console.log(circle.getDiameter());

'개발 도서 > 자바스크립트 deepdive' 카테고리의 다른 글

25 클래스  (0) 2023.07.12
16장 property attribute  (0) 2023.07.11
18 함수와 일급 객체  (0) 2023.07.11
19 프로토타입  (0) 2023.07.11
20 strict mode  (0) 2023.07.11