Skip to content

Commit

Permalink
Properly document prototype chain of generators (#34267)
Browse files Browse the repository at this point in the history
* Properly document prototype chain of generators

* Skip minify

* Remove comment

* Use shared asset

* Fix again

* Use spec-urls instead
  • Loading branch information
Josh-Cena committed Jun 24, 2024
1 parent fce408d commit 85af51e
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 8 deletions.
1 change: 0 additions & 1 deletion files/en-us/_redirects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12554,7 +12554,6 @@
/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function.displayName /en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/displayName
/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/constructor /en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toSource /en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString
/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction/prototype /en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction
/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError/prototype /en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError
/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl.RelativeTimeFormat /en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat
/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/@@toStringTag /en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Async generator methods always yield {{jsxref("Promise")}} objects.

## Constructor

The `AsyncGenerator` constructor is not available globally. Instances of `AsyncGenerator` must be returned from [async generator functions](/en-US/docs/Web/JavaScript/Reference/Statements/async_function*)
There's no JavaScript entity that corresponds to the `AsyncGenerator` constructor. Instances of `AsyncGenerator` must be returned from [async generator functions](/en-US/docs/Web/JavaScript/Reference/Statements/async_function*):

```js
async function* createAsyncGenerator() {
Expand All @@ -31,7 +31,7 @@ asyncGen.next().then((res) => console.log(res.value)); // 2
asyncGen.next().then((res) => console.log(res.value)); // 3
```

In fact, there's no JavaScript entity that corresponds to the `AsyncGenerator` constructor. There's only a hidden object which is the prototype object shared by all objects created by async generator functions. This object is often stylized as `AsyncGenerator.prototype` to make it look like a class, but it should be more appropriately called [`AsyncGeneratorFunction.prototype.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGeneratorFunction), because `AsyncGeneratorFunction` is an actual JavaScript entity.
There's only a hidden object which is the prototype object shared by all objects created by async generator functions. This object is often stylized as `AsyncGenerator.prototype` to make it look like a class, but it should be more appropriately called {{jsxref("AsyncGeneratorFunction.prototype.prototype")}}, because `AsyncGeneratorFunction` is an actual JavaScript entity. To understand the prototype chain of `AsyncGenerator` instances, see {{jsxref("AsyncGeneratorFunction.prototype.prototype")}}.

## Instance properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,15 @@ These properties are defined on `AsyncGeneratorFunction.prototype` and shared by
- {{jsxref("Object/constructor", "AsyncGeneratorFunction.prototype.constructor")}}
- : The constructor function that created the instance object. For `AsyncGeneratorFunction` instances, the initial value is the {{jsxref("AsyncGeneratorFunction/AsyncGeneratorFunction", "AsyncGeneratorFunction")}} constructor.
- `AsyncGeneratorFunction.prototype.prototype`
- : All async generator functions share the same [`prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype) property, which is [`AsyncGenerator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). Each async generator function instance also has its own `prototype` property. When the async generator function is called, the returned async generator object inherits from the async generator function's `prototype` property, which in turn inherits from `AsyncGeneratorFunction.prototype.prototype`.
- : All async generator functions share the same [`prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype) property, which is [`AsyncGenerator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). Each async generator function created with the `async function*` syntax or the `AsyncGeneratorFunction()` constructor also has its own `prototype` property, whose prototype is `AsyncGeneratorFunction.prototype.prototype`. When the async generator function is called, its `prototype` property becomes the prototype of the returned async generator object.
- `AsyncGeneratorFunction.prototype[@@toStringTag]`
- : The initial value of the [`@@toStringTag`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag) property is the string `"AsyncGeneratorFunction"`. This property is used in {{jsxref("Object.prototype.toString()")}}.

These properties are own properties of each `AsyncGeneratorFunction` instance.

- {{jsxref("AsyncGeneratorFunction/prototype", "prototype")}}
- : Used when the function is used as a constructor with the [`new`](/en-US/docs/Web/JavaScript/Reference/Operators/new) operator. It will become the new object's prototype.

## Instance methods

_Inherits instance methods from its parent {{jsxref("Function")}}_.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: AsyncGeneratorFunction.prototype.prototype
slug: Web/JavaScript/Reference/Global_Objects/AsyncGeneratorFunction/prototype
page-type: javascript-instance-data-property
spec-urls:
- https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-asyncgeneratorfunction-prototype-prototype
- https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-asyncgeneratorfunction-instances-prototype
---

{{JSRef}}

The **`prototype`** property of `AsyncGeneratorFunction.prototype` is shared by all async generator functions. Its value is [`AsyncGenerator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). Each async generator function created with the `async function*` syntax or the `AsyncGeneratorFunction()` constructor also has its own `prototype` property, whose prototype is `AsyncGeneratorFunction.prototype.prototype`. When the async generator function is called, its `prototype` property becomes the prototype of the returned async generator object.

## Value

The same object as [`AsyncGenerator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). `AsyncGeneratorFunction.prototype.prototype` is the technically more accurate name, but `AsyncGenerator.prototype` appeals to the intuition that it's the prototype of async generator objects.

{{js_property_attributes(0, 0, 1)}}

The `prototype` property of each `AsyncGeneratorFunction` instance is an empty object with no properties, whose prototype is `AsyncGeneratorFunction.prototype.prototype`. It has the following property attributes:

{{js_property_attributes(1, 0, 0)}}

## Description

An async generator function instance has two `prototype` properties. The first one is its own `prototype` property. The second one is the `prototype` property on its prototype, which is `AsyncGeneratorFunction.prototype`. (Remember that every async generator function is an instance of `AsyncGeneratorFunction`, so it has `AsyncGeneratorFunction.prototype` as its prototype.)

```js
async function* genFunc() {}
const AsyncGeneratorFunctionPrototype = Object.getPrototypeOf(genFunc);
console.log(Object.hasOwn(genFunc, "prototype")); // true
console.log(Object.hasOwn(AsyncGeneratorFunctionPrototype, "prototype")); // true
```

When an async generator function is called, the async generator function's `prototype` property becomes the prototype of the returned async generator object.

```js
const gen = genFunc();
const proto = Object.getPrototypeOf;
console.log(proto(gen) === genFunc.prototype); // true
console.log(proto(proto(gen)) === AsyncGeneratorFunctionPrototype.prototype); // true
```

The following diagram illustrates the prototype chain of an async generator function and its instances. Each hollow arrow indicates an inheritance relationship (i.e. a prototype link), and each solid arrow indicates a property relationship. Note that there's no way to access `genFunc` from `gen` — they only have an `instanceof` relationship.

![The inheritance diagram of async generators and async generator functions](https://mdn.github.io/shared-assets/images/diagrams/javascript/asyncgeneratorfunction/prototype-chain.svg)

## Specifications

{{Specifications}}

## See also

- [`async function*`](/en-US/docs/Web/JavaScript/Reference/Statements/async_function*)
- [`async function*` expression](/en-US/docs/Web/JavaScript/Reference/Operators/async_function*)
- {{jsxref("AsyncGeneratorFunction")}}
- {{jsxref("GeneratorFunction")}}
- [Inheritance and the prototype chain](/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)
- [Iterators and generators](/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The **`Generator`** object is returned by a {{jsxref("Statements/function*", "ge

## Constructor

The `Generator` constructor is not available globally. Instances of `Generator` must be returned from [generator functions](/en-US/docs/Web/JavaScript/Reference/Statements/function*):
There's no JavaScript entity that corresponds to the `Generator` constructor. Instances of `Generator` must be returned from [generator functions](/en-US/docs/Web/JavaScript/Reference/Statements/function*):

```js
function* generator() {
Expand All @@ -31,7 +31,7 @@ console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
```

In fact, there's no JavaScript entity that corresponds to the `Generator` constructor. There's only a hidden object which is the prototype object shared by all objects created by generator functions. This object is often stylized as `Generator.prototype` to make it look like a class, but it should be more appropriately called [`GeneratorFunction.prototype.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction), because `GeneratorFunction` is an actual JavaScript entity.
There's only a hidden object which is the prototype object shared by all objects created by generator functions. This object is often stylized as `Generator.prototype` to make it look like a class, but it should be more appropriately called {{jsxref("GeneratorFunction.prototype.prototype")}}, because `GeneratorFunction` is an actual JavaScript entity. To understand the prototype chain of `Generator` instances, see {{jsxref("GeneratorFunction.prototype.prototype")}}.

## Instance properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ These properties are defined on `GeneratorFunction.prototype` and shared by all

- {{jsxref("Object/constructor", "GeneratorFunction.prototype.constructor")}}
- : The constructor function that created the instance object. For `GeneratorFunction` instances, the initial value is the {{jsxref("GeneratorFunction/GeneratorFunction", "GeneratorFunction")}} constructor.
- `GeneratorFunction.prototype.prototype`
- : All generator functions share the same [`prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype) property, which is [`Generator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). Each generator function instance also has its own `prototype` property. When the generator function is called, the returned generator object inherits from the generator function's `prototype` property, which in turn inherits from `GeneratorFunction.prototype.prototype`.
- {{jsxref("GeneratorFunction.prototype.prototype")}}
- : All generator functions share the same [`prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype) property, which is [`Generator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). Each generator function created with the `function*` syntax or the `GeneratorFunction()` constructor also has its own `prototype` property, whose prototype is `GeneratorFunction.prototype.prototype`. When the generator function is called, its `prototype` property becomes the prototype of the returned generator object.
- `GeneratorFunction.prototype[@@toStringTag]`
- : The initial value of the [`@@toStringTag`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag) property is the string `"GeneratorFunction"`. This property is used in {{jsxref("Object.prototype.toString()")}}.

These properties are own properties of each `GeneratorFunction` instance.

- {{jsxref("GeneratorFunction/prototype", "prototype")}}
- : Used when the function is used as a constructor with the [`new`](/en-US/docs/Web/JavaScript/Reference/Operators/new) operator. It will become the new object's prototype.

## Instance methods

_Inherits instance methods from its parent {{jsxref("Function")}}_.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: GeneratorFunction.prototype.prototype
slug: Web/JavaScript/Reference/Global_Objects/GeneratorFunction/prototype
page-type: javascript-instance-data-property
spec-urls:
- https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-generatorfunction.prototype.prototype
- https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-generatorfunction-instances-prototype
---

{{JSRef}}

The **`prototype`** property of `GeneratorFunction.prototype` is shared by all generator functions. Its value is [`Generator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). Each generator function created with the `function*` syntax or the `GeneratorFunction()` constructor also has its own `prototype` property, whose prototype is `GeneratorFunction.prototype.prototype`. When the generator function is called, its `prototype` property becomes the prototype of the returned generator object.

## Value

The same object as [`Generator.prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). `GeneratorFunction.prototype.prototype` is the technically more accurate name, but `Generator.prototype` appeals to the intuition that it's the prototype of generator objects.

{{js_property_attributes(1, 0, 0)}}

The `prototype` property of each `GeneratorFunction` instance is an empty object with no properties, whose prototype is `GeneratorFunction.prototype.prototype`. It has the following property attributes:

{{js_property_attributes(0, 0, 1)}}

## Description

A generator function instance has two `prototype` properties. The first one is its own `prototype` property. The second one is the `prototype` property on its prototype, which is `GeneratorFunction.prototype`. (Remember that every generator function is an instance of `GeneratorFunction`, so it has `GeneratorFunction.prototype` as its prototype.)

```js
function* genFunc() {}
const GeneratorFunctionPrototype = Object.getPrototypeOf(genFunc);
console.log(Object.hasOwn(genFunc, "prototype")); // true
console.log(Object.hasOwn(GeneratorFunctionPrototype, "prototype")); // true
```

When a generator function is called, the generator function's `prototype` property becomes the prototype of the returned generator object.

```js
const gen = genFunc();
const proto = Object.getPrototypeOf;
console.log(proto(gen) === genFunc.prototype); // true
console.log(proto(proto(gen)) === GeneratorFunctionPrototype.prototype); // true
```

The following diagram illustrates the prototype chain of a generator function and its instances. Each hollow arrow indicates an inheritance relationship (i.e. a prototype link), and each solid arrow indicates a property relationship. Note that there's no way to access `genFunc` from `gen` — they only have an `instanceof` relationship.

![The inheritance diagram of generators and generator functions](https://mdn.github.io/shared-assets/images/diagrams/javascript/generatorfunction/prototype-chain.svg)

## Specifications

{{Specifications}}

## See also

- [`function*`](/en-US/docs/Web/JavaScript/Reference/Statements/function*)
- [`function*` expression](/en-US/docs/Web/JavaScript/Reference/Operators/function*)
- {{jsxref("AsyncGeneratorFunction")}}
- {{jsxref("GeneratorFunction")}}
- [Inheritance and the prototype chain](/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)
- [Iterators and generators](/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators)

0 comments on commit 85af51e

Please sign in to comment.