功能:prototype

当函数用作带有 new 运算符的构造函数时,将使用 Function 实例的 prototype 数据属性。它将成为新对象的原型。

¥The prototype data property of a Function instance is used when the function is used as a constructor with the new operator. It will become the new object's prototype.

注意:并非所有 Function 对象都具有 prototype 属性 — 请参阅 description

¥Note: Not all Function objects have the prototype property — see description.

¥Value

一个东西。

¥An object.

Property attributes of 功能:prototype
Writable yes
Enumerable no
Configurable no

注意: 是一种函数类型,因此这里的大部分描述也适用于类的 prototype 属性。唯一显着的区别是类的 prototype 属性不可写。

¥Note: Classes are a type of function, so most of the description here applies to the prototype property of classes too. The only salient difference is that the prototype property of a class is not writable.

描述

¥Description

当使用 new 调用函数时,构造函数的 prototype 属性将成为结果对象的原型。

¥When a function is called with new, the constructor's prototype property will become the resulting object's prototype.

js
function Ctor() {}
const inst = new Ctor();
console.log(Object.getPrototypeOf(inst) === Ctor.prototype); // true

你可以阅读 继承和原型链 以获取有关构造函数的 prototype 属性和结果对象原型之间交互的更多信息。

¥You can read Inheritance and the prototype chain for more information about the interactions between a constructor function's prototype property and the resulting object's prototype.

具有 prototype 属性的函数不足以使其有资格作为构造函数。生成器功能prototype 属性,但不能用 new 调用:

¥A function having a prototype property is not sufficient for it to be eligible as a constructor. Generator functions have a prototype property, but cannot be called with new:

js
async function* asyncGeneratorFunction() {}
function* generatorFunction() {}

相反,当在没有 new 的情况下调用生成器函数时,将使用生成器函数的 prototype 属性。prototype 属性将成为返回的 Generator 对象的原型。

¥Instead, generator functions' prototype property is used when they are called without new. The prototype property will become the returned Generator object's prototype.

此外,某些函数可能具有 prototype,但在使用 new 调用时会无条件抛出。例如,当使用 new 调用 Symbol()BigInt() 函数时,会抛出异常,因为 Symbol.prototypeBigInt.prototype 只是为了提供原始值的方法,但不应该直接构造封装对象。

¥In addition, some functions may have a prototype but throw unconditionally when called with new. For example, the Symbol() and BigInt() functions throw when called with new, because Symbol.prototype and BigInt.prototype are only intended to provide methods for the primitive values, but the wrapper objects should not be directly constructed.

以下函数没有 prototype,因此不适合作为构造函数,即使稍后手动分配 prototype 属性也是如此:

¥The following functions do not have prototype, and are therefore ineligible as constructors, even if a prototype property is later manually assigned:

js
const method = { foo() {} }.foo;
const arrowFunction = () => {};
async function asyncFunction() {}

以下是具有 prototype 的有效构造函数:

¥The following are valid constructors that have prototype:

js
class Class {}
function fn() {}

绑定函数 没有 prototype 属性,但可能是可构造的。当它被构造时,目标函数被构造,如果目标函数是可构造的,它将返回一个普通实例。

¥A bound function does not have a prototype property, but may be constructable. When it's constructed, the target function is constructed instead, and if the target function is constructable, it would return a normal instance.

js
const boundFunction = function () {}.bind(null);

默认情况下,函数的 prototype 属性是一个具有一个属性的普通对象:constructor,这是对函数本身的引用。constructor 属性是可写、不可枚举且可配置的。

¥A function's prototype property, by default, is a plain object with one property: constructor, which is a reference to the function itself. The constructor property is writable, non-enumerable, and configurable.

如果函数的 prototype 被重新分配为 Object 以外的其他值,则当使用 new 调用该函数时,返回的对象的原型将是 Object.prototype。(换句话说,new 忽略 prototype 属性并构造一个普通对象。)

¥If the prototype of a function is reassigned with something other than an Object, when the function is called with new, the returned object's prototype would be Object.prototype instead. (In other words, new ignores the prototype property and constructs a plain object.)

js
function Ctor() {}
Ctor.prototype = 3;
console.log(Object.getPrototypeOf(new Ctor()) === Object.prototype); // true

示例

¥Examples

通过改变原型属性来更改所有实例的原型

¥Changing the prototype of all instances by mutating the prototype property

js
function Ctor() {}
const p1 = new Ctor();
const p2 = new Ctor();
Ctor.prototype.prop = 1;
console.log(p1.prop); // 1
console.log(p2.prop); // 1

将非方法属性添加到类的原型属性中

¥Adding a non-method property to a class's prototype property

类字段 向每个实例添加属性。类方法在原型上声明函数属性。但是,无法向原型添加非功能属性。如果你想在所有实例之间共享静态数据(例如,所有错误实例之间的 Error.prototype.name 相同),你可以手动将其分配到类的 prototype 上。

¥Class fields add properties to each instance. Class methods declare function properties on the prototype. However, there's no way to add a non-function property to the prototype. In case you want to share static data between all instances (for example, Error.prototype.name is the same between all error instances), you can manually assign it on the prototype of a class.

js
class Dog {
  constructor(name) {
    this.name = name;
  }
}

Dog.prototype.species = "dog";

console.log(new Dog("Jack").species); // "dog"

使用 静态初始化块 可以使这更符合人机工程学,静态初始化块 在类初始化时调用。

¥This can be made more ergonomic using static initialization blocks, which are called when the class is initialized.

js
class Dog {
  static {
    Dog.prototype.species = "dog";
  }
  constructor(name) {
    this.name = name;
  }
}

console.log(new Dog("Jack").species); // "dog"

规范

Specification
ECMAScript Language Specification
# sec-function-instances-prototype

¥Specifications

也可以看看