Date 与 new Date() 有何区别

发布: (2026年2月7日 GMT+8 22:00)
5 分钟阅读
原文: Dev.to

抱歉,我需要您提供要翻译的完整文本内容。请把文章的其余部分粘贴在这里,我会帮您将其翻译成简体中文,并保留原始的格式和代码块。

介绍

昨天我深入研究了构造函数签名。今天我们将看看使用 new 关键字(构造函数签名)和直接调用函数(调用签名)之间的区别,尤其是针对像 Date 这样的内置对象。

如果你还没有阅读过关于调用构造函数的内容,请查看这篇文章:
Build a simple mini‑dayjs clone logger middleware by call signatures in TypeScript

构造函数 vs. 调用签名

在 JavaScript 中,你可能会看到如下代码:

Boolean();
new Date();
new Array();
new Promise(() => {});

区别如下:

签名使用方式返回值
构造函数(需要 newnew Date();对象(实例)
调用(函数调用)Date();dayjs();原始值(或函数返回的任何值)

为什么 new 返回对象

new 会创建一个 实例,而实例必须是对象,这样它才能拥有属性、方法以及原型链。原始值无法具备这些特性,因此语言设计规定 new 必须返回对象。

console.log(typeof String);            // function
console.log(typeof String.prototype); // object
console.log(typeof new String());      // object

Source:

原型继承概述

JavaScript 提供三种实现原型继承的方式:

  1. 对象字面量
  2. 构造函数

使用类的示例

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:为构造函数和调用签名添加类型

您可以描述一种类型,使其既可以作为构造函数(使用 new)又可以作为普通函数(调用签名)使用。

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 内部机制 – 了解对象、原型和实例是如何创建的。

希望这能阐明它们之间的区别。祝编码愉快! 🚀

0 浏览
Back to Blog

相关文章

阅读更多 »

Var vs Let:大混淆解析!

封面图片:'Var vs Let: The Big Confusion Explained!' https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A...

Scrap Labs – 金属3D打印机

真实金属打印。由废料构建。 在Scrap Labs,我们的使命是通过最先进的金属打印技术赋能建设者和创作者,使其……