new

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

new 運算子允許開發者建立一個使用者定義的物件型別或內建物件型別之一的例項,這些物件型別都具有建構函式。

試一試

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const car1 = new Car("Eagle", "Talon TSi", 1993);

console.log(car1.make);
// Expected output: "Eagle"

語法

js
new constructor
new constructor()
new constructor(arg1)
new constructor(arg1, arg2)
new constructor(arg1, arg2, /* …, */ argN)

引數

constructor

指定物件例項型別的類或函式。該表示式可以是任何具有足夠優先順序的內容,包括識別符號、屬性訪問器或另一個 new 表示式,但不允許使用可選鏈式運算子

arg1, arg2, …, argN

將傳遞給 constructor 的值列表。new Foo 等同於 new Foo(),即,如果沒有指定引數列表,Foo 將在沒有引數的情況下被呼叫。

描述

當一個函式使用 new 關鍵字呼叫時,該函式將被用作建構函式。new 將執行以下操作:

  1. 建立一個空白的普通 JavaScript 物件。為方便起見,我們稱之為 newInstance

  2. 如果建構函式的 prototype 屬性是一個 Object,則將 newInstance 的 [[Prototype]] 指向建構函式的 prototype 屬性。否則,newInstance 仍將是一個普通物件,其 [[Prototype]] 為 Object.prototype

    注意:新增到建構函式的 prototype 屬性中的屬性/物件因此可供由該建構函式建立的所有例項訪問。

  3. 使用給定引數執行建構函式,將 newInstance 繫結為 this 上下文(即,建構函式中所有對 this 的引用現在都指向 newInstance)。

  4. 如果建構函式返回一個非原始值,則此返回值將成為整個 new 表示式的結果。否則,如果建構函式不返回任何內容或返回原始值,則返回 newInstance。(通常建構函式不返回值,但它們可以選擇這樣做以覆蓋正常的物件建立過程。)

只能使用 new 運算子例項化——嘗試不使用 new 呼叫類將丟擲 TypeError

使用使用者定義的建構函式建立物件需要兩個步驟:

  1. 透過編寫一個指定其名稱和屬性的函式來定義物件型別。例如,一個用於建立物件 Foo 的建構函式可能如下所示:

    js
    function Foo(bar1, bar2) {
      this.bar1 = bar1;
      this.bar2 = bar2;
    }
    
  2. 使用 new 建立物件的例項。

    js
    const myFoo = new Foo("Bar 1", 2021);
    

注意:一個物件可以有一個屬性,該屬性本身是另一個物件。請參閱下面的示例。

你總是可以向先前定義的物件例項新增屬性。例如,語句 car1.color = "black"car1 添加了一個屬性 color,併為其賦值 "black"

然而,這不影響任何其他物件。要將新屬性新增到所有相同型別的物件,你必須將該屬性新增到建構函式的 prototype 屬性中。這定義了一個由該函式建立的所有物件共享的屬性,而不是僅僅由該物件型別的一個例項共享的屬性。以下程式碼向所有 Car 型別的物件新增一個值為 "original color"color 屬性,然後僅在例項物件 car1 中將其值覆蓋為字串 "black"。有關更多資訊,請參閱原型

js
function Car() {}
const car1 = new Car();
const car2 = new Car();

console.log(car1.color); // undefined

Car.prototype.color = "original color";
console.log(car1.color); // 'original color'

car1.color = "black";
console.log(car1.color); // 'black'

console.log(Object.getPrototypeOf(car1).color); // 'original color'
console.log(Object.getPrototypeOf(car2).color); // 'original color'
console.log(car1.color); // 'black'
console.log(car2.color); // 'original color'

注意:雖然建構函式可以像任何常規函式一樣被呼叫(即,不帶 new 運算子),但在這種情況下不會建立新物件,並且 this 的值也不同。

一個函式可以透過檢查 new.target 來判斷它是否使用 new 呼叫。只有當函式在沒有 new 的情況下被呼叫時,new.target 才是 undefined。例如,你可以有一個函式,它在被呼叫時和被構造時表現不同:

js
function Car(color) {
  if (!new.target) {
    // Called as function.
    return `${color} car`;
  }
  // Called with new.
  this.color = color;
}

const a = Car("red"); // a is "red car"
const b = new Car("red"); // b is `Car { color: "red" }`

在 ES6 引入之前,大多數 JavaScript 內建物件既可呼叫又可構造,儘管它們中的許多表現出不同的行為。舉幾個例子:

  • Array()Error()Function() 作為函式或建構函式呼叫時行為相同。
  • Boolean()Number()String() 在作為函式呼叫時將其引數強制轉換為相應的原始型別,在構造時返回包裝物件。
  • Date() 在作為函式呼叫時返回一個表示當前日期的字串,等同於 new Date().toString()

ES6 之後,語言對哪些是建構函式,哪些是函式變得更加嚴格。例如:

  • Symbol()BigInt() 只能在不帶 new 的情況下呼叫。嘗試構造它們將丟擲 TypeError
  • ProxyMap 只能用 new 構造。嘗試呼叫它們將丟擲 TypeError

示例

物件型別和物件例項

假設你想要為汽車建立一種物件型別。你希望這種型別的物件被稱為 Car,並且你希望它具有品牌、型號和年份的屬性。為此,你將編寫以下函式:

js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

現在你可以按如下方式建立名為 myCar 的物件

js
const myCar = new Car("Eagle", "Talon TSi", 1993);

此語句建立 myCar 併為其屬性分配指定的值。然後 myCar.make 的值是字串 "Eagle",myCar.year 是整數 1993,等等。

你可以透過呼叫 new 建立任意數量的 car 物件。例如:

js
const kensCar = new Car("Nissan", "300ZX", 1992);

本身是另一個物件的物件屬性

假設你定義一個名為 Person 的物件,如下所示:

js
function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}

然後例項化兩個新的 Person 物件,如下所示:

js
const rand = new Person("Rand McNally", 33, "M");
const ken = new Person("Ken Jones", 39, "M");

然後你可以重寫 Car 的定義,以包含一個接受 Person 物件的 owner 屬性,如下所示:

js
function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}

要例項化新物件,你可以使用以下內容:

js
const car1 = new Car("Eagle", "Talon TSi", 1993, rand);
const car2 = new Car("Nissan", "300ZX", 1992, ken);

在建立新物件時,上述語句不是傳遞字面字串或整數值,而是將物件 randken 作為所有者的引數傳遞。要查明 car2 的所有者姓名,你可以訪問以下屬性:

js
car2.owner.name;

new 與類一起使用

js
class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const p = new Person("Caroline");
p.greet(); // Hello, my name is Caroline

規範

規範
ECMAScript® 2026 語言規範
# sec-new-operator

瀏覽器相容性

另見