new
new
运算符允许开发者创建用户定义的对象类型或具有构造函数的内置对象类型之一的实例。
¥The new
operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function.
Try it
语法
参数
¥Parameters
constructor
-
指定对象实例类型的类或函数。表达式可以是任何具有足够 precedence 的内容,包括标识符、属性访问权 或另一个
new
表达式,但不允许使用 可选链接。 arg1
,arg2
, …,argN
-
调用
constructor
时使用的值列表。new Foo
相当于new Foo()
,即如果未指定参数列表,则不带参数调用Foo
。
描述
¥Description
当使用 new
关键字调用函数时,该函数将被用作构造函数。new
将做以下事情:
¥When a function is called with the new
keyword, the function will be used as a constructor. new
will do the following things:
- 创建一个空白的、纯 JavaScript 对象。为了方便起见,我们将其称为
newInstance
。 - 如果
prototype
是Object
,则将newInstance
的 [[Prototype]] 指向构造函数的prototype
属性。否则,newInstance
保持为普通对象,并以Object.prototype
作为其 [[Prototype]]。注意:因此,从构造函数创建的所有实例都可以访问添加到构造函数的
prototype
属性的属性/对象。¥Note: Properties/objects added to the constructor function's
prototype
property are therefore accessible to all instances created from the constructor function. - 使用给定参数执行构造函数,将
newInstance
绑定为this
上下文(即构造函数中对this
的所有引用现在都引用newInstance
)。 - 如果构造函数返回 non-primitive,则该返回值将成为整个
new
表达式的结果。否则,如果构造函数不返回任何内容或返回原语,则返回newInstance
。(通常构造函数不返回值,但它们可以选择这样做来覆盖正常的对象创建过程。)
类 只能使用 new
运算符实例化 - 尝试调用没有 new
的类将抛出 TypeError
。
¥Classes can only be instantiated with the new
operator — attempting to call a class without new
will throw a TypeError
.
使用用户定义的构造函数创建对象需要两个步骤:
¥Creating an object with a user-defined constructor function requires two steps:
- 通过编写指定对象名称和属性的函数来定义对象类型。例如,创建对象
Foo
的构造函数可能如下所示:jsfunction Foo(bar1, bar2) { this.bar1 = bar1; this.bar2 = bar2; }
- 使用
new
创建对象的实例。jsconst myFoo = new Foo("Bar 1", 2021);
注意:一个对象可以拥有一个属性,该属性本身就是另一个对象。请参阅下面的示例。
¥Note: An object can have a property that is itself another object. See the examples below.
你始终可以向先前定义的对象实例添加属性。例如,语句 car1.color = "black"
将属性 color
添加到 car1
,并为其分配值 "black"
。
¥You can always add a property to a previously defined object instance. For example, the statement car1.color = "black"
adds a property color
to car1
, and assigns it a value of "black"
.
但是,这不会影响任何其他对象。要将新属性添加到同一类型的所有对象,必须将该属性添加到构造函数的 prototype
属性。这定义了一个由使用该函数创建的所有对象共享的属性,而不仅仅是该对象类型的一个实例。以下代码将值为 "original color"
的 color
属性添加到类型 Car
的所有对象中,然后仅在实例对象 car1
中使用字符串 "black"
覆盖该值。欲了解更多信息,请参阅 prototype。
¥However, this does not affect any other objects. To add the new property to all objects of the same type, you must add the property to the constructor's prototype
property. This defines a property that is shared by all objects created with that function, rather than by just one instance of the object type. The following code adds a color
property with value "original color"
to all objects of type Car
, and then overwrites that value with the string "black"
only in the instance object car1
. For more information, see prototype.
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
的值也不同。¥Note: While the constructor function can be invoked like any regular function (i.e. without the
new
operator), in this case a new object is not created and the value ofthis
is also different.
函数可以通过检查 new.target
来知道它是否被 new
调用。当调用函数而没有 new
时,new.target
只有 undefined
。例如,你可以拥有一个在调用时和构造时表现不同的函数:
¥A function can know whether it is invoked with new
by checking new.target
. new.target
is only undefined
when the function is invoked without new
. For example, you can have a function that behaves differently when it's called versus when it's constructed:
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" }`
在引入 classes 的 ES6 之前,大多数 JavaScript 内置函数都是可调用和可构造的,尽管其中许多表现出不同的行为。仅举几例:
¥Prior to ES6, which introduced classes, most JavaScript built-ins are both callable and constructible, although many of them exhibit different behaviors. To name a few:
- 当作为函数或构造函数调用时,
Array()
、Error()
和Function()
的行为相同。 Boolean()
、Number()
和String()
在调用时将其参数强制转换为各自的原始类型,并在构造时返回封装对象。Date()
调用时返回表示当前日期的字符串,相当于new Date().toString()
。
ES6 之后,该语言对于哪些是构造函数、哪些是函数更加严格。例如:
¥After ES6, the language is stricter about which are constructors and which are functions. For example:
示例
对象类型和对象实例
¥Object type and object instance
假设你要为汽车创建一个对象类型。你希望这种类型的对象被称为 Car
,并且你希望它具有品牌、型号和年份属性。为此,你需要编写以下函数:
¥Suppose you want to create an object type for cars. You want this type of object to be
called Car
, and you want it to have properties for make, model, and year.
To do this, you would write the following function:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
现在你可以创建一个名为 myCar
的对象,如下所示:
¥Now you can create an object called myCar
as follows:
const myCar = new Car("Eagle", "Talon TSi", 1993);
该语句创建 myCar
并为其属性分配指定的值。那么 myCar.make
的值就是字符串 "鹰",myCar.year
就是整数 1993,依此类推。
¥This statement creates myCar
and assigns it the specified values for its
properties. Then the value of myCar.make
is the string "Eagle",
myCar.year
is the integer 1993, and so on.
你可以通过调用 new
创建任意数量的 car
对象。例如:
¥You can create any number of car
objects by calls to new
. For
example:
const kensCar = new Car("Nissan", "300ZX", 1992);
对象属性本身就是另一个对象
¥Object property that is itself another object
假设你定义了一个名为 Person
的对象,如下所示:
¥Suppose you define an object called Person
as follows:
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
然后实例化两个新的 Person
对象如下:
¥And then instantiate two new Person
objects as follows:
const rand = new Person("Rand McNally", 33, "M");
const ken = new Person("Ken Jones", 39, "M");
然后,你可以重写 Car
的定义以包含采用 Person
对象的 owner
属性,如下所示:
¥Then you can rewrite the definition of Car
to include an
owner
property that takes a Person
object, as follows:
function Car(make, model, year, owner) {
this.make = make;
this.model = model;
this.year = year;
this.owner = owner;
}
要实例化新对象,请使用以下命令:
¥To instantiate the new objects, you then use the following:
const car1 = new Car("Eagle", "Talon TSi", 1993, rand);
const car2 = new Car("Nissan", "300ZX", 1992, ken);
上述语句在创建新对象时没有传递文字字符串或整数值,而是将对象 rand
和 ken
作为所有者的参数传递。要查找 car2
所有者的名称,你可以访问以下属性:
¥Instead of passing a literal string or integer value when creating the new objects, the
above statements pass the objects rand
and ken
as the
parameters for the owners. To find out the name of the owner of car2
, you
can access the following property:
car2.owner.name;
将 new
与类一起使用
规范
Specification |
---|
ECMAScript Language Specification # sec-new-operator |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also