`Date`와 `new Date()`의 차이점은 무엇인가요?
Source: Dev.to
위의 링크에 있는 전체 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다. 코드 블록이나 URL은 그대로 유지하고, 마크다운 형식과 기술 용어는 그대로 보존하겠습니다.
소개
어제 저는 생성자 시그니처에 대해 깊이 파고들었습니다. 오늘은 new 키워드(생성자 시그니처)를 사용하는 것과 함수를 직접 호출하는 것(호출 시그니처)의 차이점을, 특히 Date와 같은 내장 객체를 중심으로 살펴보겠습니다.
아직 호출 생성자에 대해 읽어보지 않으셨다면, 이 글을 확인해 보세요:
TypeScript에서 호출 시그니처를 사용한 간단한 미니‑dayjs 클론 로거 미들웨어 만들기
Constructor vs. Call Signatures
JavaScript에서는 다음과 같은 코드를 볼 수 있습니다:
Boolean();
new Date();
new Array();
new Promise(() => {});
차이점은 다음과 같습니다:
| 서명 | 사용 방법 | 반환값 |
|---|---|---|
Constructor (new 필요) | new Date(); | 객체 (인스턴스) |
| Call (함수 호출) | Date(); 혹은 dayjs(); | 원시값 (또는 함수가 반환하는 값) |
new가 객체를 반환하는 이유
new는 인스턴스를 생성하며, 인스턴스는 속성, 메서드, 프로토타입 체인을 가질 수 있어야 하기 때문에 객체여야 합니다. 원시값은 이러한 기능을 가질 수 없으므로, 언어 설계상 new는 객체를 반환하도록 강제합니다.
console.log(typeof String); // function
console.log(typeof String.prototype); // object
console.log(typeof new String()); // object
프로토타입 상속 개요
JavaScript는 프로토타입 상속을 구현하는 세 가지 방법을 제공합니다:
- 객체 리터럴
- 생성자 함수
- 클래스
클래스 예시
class Human {}
console.log(typeof new Human()); // object
생성자 함수를 이용한 예시
function Animal() {}
Animal.prototype.eat = function () {
console.log("Nhoammmm");
};
function inheritPrototype(proto) {
function ChainLink() {}
ChainLink.prototype = proto;
return new ChainLink();
}
function Human() {}
Human.prototype = inheritPrototype(Animal.prototype);
Human.prototype.work = function () {
console.log("Coding and earning money!");
};
const kelvynThai = new Human();
console.log(kelvynThai instanceof Human); // true
console.log(typeof kelvynThai); // object
kelvynThai.work(); // Coding and earning money!
kelvynThai.eat(); // Nhoammmm
TypeScript: 생성자와 호출 시그니처 타입 지정
You can describe a type that works both as a constructor (with new) and as a regular function (call signature).
type MyDate = {
// Constructor signature – returns a String object
new (dateStr: string): String;
// Call signature – returns a primitive string
(dateNum?: number): string;
};
const MyDate: MyDate = function (this: unknown, d?: string | number) {
if (new.target) {
// When called with `new`, return a String object
return new String(`PARSED_DATE:${d}`);
}
// When called as a function, return a primitive string
return d !== undefined ? `TIMESTAMP:${d}` : "DEFAULT_DATE";
} as MyDate;
// Using the constructor
const dateWithNew = new MyDate("Sat 7 Feb 2026");
console.log(dateWithNew, typeof dateWithNew);
// [String: 'PARSED_DATE:Sat 7 Feb 2026'] object
// Using the call signature
const dateWithoutNew = MyDate(123456);
console.log(dateWithoutNew, typeof dateWithoutNew);
// TIMESTAMP:123456 string
// Built‑in example
console.log(new Date(), typeof new Date());
// 2026-02-07T13:58:57.212Z object
사고 모델
new→ 객체(인스턴스)를 생성합니다.- 직접 호출 → 원시값(또는 함수가 반환하는 어떤 값)이 반환됩니다.
이 모델을 이해하면 TypeScript에서 생성자 타입을 정의하고 사용하는 것이 훨씬 쉬워집니다.
이 지식이 도움이 될 때
- 내장 API 읽기 – 함수가
new를 필요로 하는지 여부를 파악합니다. - 유연한 라이브러리 설계 – 적절할 때 생성자와 호출 시그니처를 모두 노출합니다.
- TypeScript에서 함수 동작 모델링 – 정확한 타입 정의를 작성합니다.
- JavaScript 내부 구조 파악 – 객체, 프로토타입, 인스턴스가 어떻게 생성되는지 확인합니다.
차이점을 명확히 이해하는 데 도움이 되길 바랍니다. 즐거운 코딩 되세요! 🚀