본문 바로가기
Programming/자바스크립트

[자바스크립트] Constructor vs Non-Constructor

by 코딩하는 랄로 2023. 11. 9.
728x90

함수의 구분 : Constructor vs Non-Constructor

자바스크립트의 함수는 객체를 생성하는 생성자 함수로도 사용되고 콜백 함수, 메서드 등 여러 곳에서 사용된다. 자바스크립트 엔진은 이러한 함수들을 평가하여 함수 객체를 생성하는데, 함수 정의 방식에 따라 함수를 constructor와 non-constructor로 구분한다.

 

constructor 는 생성자를 뜻하는 말로, constructor로 구분된 함수로는 new 키워드를 통해 객체를 생성하는 것이 가능하다. 하지만 non-constructor로 구분된 함수는 new 키워드를 통해 객체를 생성할 수 없고 오로지 함수로서의 사용만이 가능하다.

 

자바스크립트에서 어떤 함수가 constructor인지, non-constructor인지 알아보자.

 

 

 

constructor

자바스크립트에서 constructor로 구분하는 함수로는 다음과 같다.

  • 함수 선언문
  • 함수 표현식
  • 클래스

일반적으로, 흔히 사용하는 함수 선언문, 함수 표현식은 constructor로 구분되는 함수이고, 클래스 또한 constructor로 구분되는 함수이다. 클래스가 함수였어? 라는 의문점이 생길 수 있지만, 지금은 자바스크립트에서 클래스는 함수의 한 종류이다라는 것만 기억하고 해당 내용에 대한 것은 추후 포스팅에서 다루겠다. 

// 함수 선언문
function conFunc() {
    console.log("constructor function")
}

// 함수로 사용
conFunc(); // constructor function
console.log(typeof conFunc);  // function

// new 키워드 사용 => 작동함
let obj = new conFunc(); // constructor function
console.log(typeof obj); // object


// 함수 표현식
const conFunc2 = function() {
    console.log("constructor function");
}

conFunc2();  // constructor function
console.log(typeof conFunc2);  // funtion

obj = new conFunc2();  // constructor function
console.log(typeof obj);  // object


// 클래스
class ConFunc3 { }

console.log(typeof ConFunc3);  //function
console.log(typeof (new ConFunc3()));  //object

 

자바스크립트의 모든 함수에는 내부 메소드 [[Call]]이 선언이 되어있고, 함수를 호출할 때 해당 메소드를 통해 호출하게 된다. 또한 constructor로 구분되는 함수 내부에는 [[Construct]] 메소드가 있기 때문에 new 키워드를 사용하면 [[Call]] 대시 [[Construct]]를 호출하게 되어 객체를 생성하게 되는 것이다.

 

그렇기 떄문에, 위의 예제 코드를 보면 일반 함수로 사용하면 function 타입을 출력하지만 new를 통해 객체를 생성하게 되면 object를 출력하는 것을 확인할 수 있다.

 

 

 

non-constructor

non-constructor로 구분되는 함수는 다음과 같다.

  • 메소드 (ES6부터는 축약 표현 메소드)
  • 화살표 함수

일반적으로 함수를 프로퍼티 값으로 사용하면 메소드라고 통칭하지만, ES6부터는 메서드 축약 표현으로 표현된 함수만 메소드라고 한다. 해당 함수가 어떻게 정의되었냐에 따라, constructor와 non-constructor인지 구분하는 것이다.

// 축약 표현 X 메소드
const obj = {
    print : function() {
        console.log("hi");
    }
}

console.log(typeof obj.print); // function

// new 키워드를 사용할 수 있다??
// => 축약 표현을 사용하지 않은 함수는 메소드가 아닌 일반 constructor 함수로 구분
console.log(typeof (new obj.print())); // object


// 축약 표현 O 메소드
const obj2 = {
    print() { console.log('hi') }
}

console.log(typeof obj2.print); // function
// new 생성자 사용시 오류 발생!!!
console.log(typeof (new obj2.print())) // TypeError: obj2.print is not a constructor


// 화살표 함수도 non-constructor 함수
const arrowFunc = () => {
    console.log("arrow function")
}

console.log(typeof arrowFunc);  // function
console.log(typeof (new arrowFunc()));  // TypeError: arrowFunc is not a constructor

 

non-constructor 함수의 경우, 내부 메소드로 [[Construct]]가 선언되어 있지 않기 때문에 new 키워드를 사용할 경우, 해당 함수는 is not a constructor라고 에러를 띄우게 되는 것이다.

 

 

 

주의할 점

constructor 함수는 new 키워드를 통해 객체를 생성할 수 있다. 그렇기 때문에, 일반 함수와 생성자 함수를 구분하기 쉽지 않다. 그렇기 때문에 아래와 같은 상황에서 예상치 못한 결과들을 마주하게 되는 것이다.

 

생성자 함수와 비슷한 이름의 일반함수가 존재할 때 실수로 일반함수로 객체를 생성...

function person() {}

function pearson() {
    this.name = 'pearson',
    this.description = 'this is not person function'
}

const p = new person();
console.log(p.name);  // => undefined

 

이러한 경우를 방지하고자, 자바스크립트에서는 암묵적으로 생성자 함수의 경우는 이름을 대문자로 시작하여 해당 함수가 객체를 생성하기 위한 생성자 함수임을 명시한다.

728x90