From 85af51e61dd95fa85feb7c43e08f284992ba69e5 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 24 Jun 2024 05:56:45 -0400 Subject: [PATCH] Properly document prototype chain of generators (#34267) * Properly document prototype chain of generators * Skip minify * Remove comment * Use shared asset * Fix again * Use spec-urls instead --- files/en-us/_redirects.txt | 1 - .../global_objects/asyncgenerator/index.md | 4 +- .../asyncgeneratorfunction/index.md | 7 ++- .../asyncgeneratorfunction/prototype/index.md | 59 +++++++++++++++++++ .../global_objects/generator/index.md | 4 +- .../global_objects/generatorfunction/index.md | 9 ++- .../generatorfunction/prototype/index.md | 59 +++++++++++++++++++ 7 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/prototype/index.md create mode 100644 files/en-us/web/javascript/reference/global_objects/generatorfunction/prototype/index.md diff --git a/files/en-us/_redirects.txt b/files/en-us/_redirects.txt index a0001925fdfc200..3ec82d9b838fe0e 100644 --- a/files/en-us/_redirects.txt +++ b/files/en-us/_redirects.txt @@ -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 diff --git a/files/en-us/web/javascript/reference/global_objects/asyncgenerator/index.md b/files/en-us/web/javascript/reference/global_objects/asyncgenerator/index.md index 87a5720ea663501..cf3d7d1fc0b61e9 100644 --- a/files/en-us/web/javascript/reference/global_objects/asyncgenerator/index.md +++ b/files/en-us/web/javascript/reference/global_objects/asyncgenerator/index.md @@ -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() { @@ -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 diff --git a/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/index.md b/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/index.md index 5ceeeca545cccad..623048ba0ced06c 100644 --- a/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/index.md +++ b/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/index.md @@ -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")}}_. diff --git a/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/prototype/index.md b/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/prototype/index.md new file mode 100644 index 000000000000000..29f8b4b18438b0b --- /dev/null +++ b/files/en-us/web/javascript/reference/global_objects/asyncgeneratorfunction/prototype/index.md @@ -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) diff --git a/files/en-us/web/javascript/reference/global_objects/generator/index.md b/files/en-us/web/javascript/reference/global_objects/generator/index.md index c8041812e5cbb4a..633b65b3c3fcc70 100644 --- a/files/en-us/web/javascript/reference/global_objects/generator/index.md +++ b/files/en-us/web/javascript/reference/global_objects/generator/index.md @@ -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() { @@ -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 diff --git a/files/en-us/web/javascript/reference/global_objects/generatorfunction/index.md b/files/en-us/web/javascript/reference/global_objects/generatorfunction/index.md index de2120a8ced0311..8fac0d10d832a82 100644 --- a/files/en-us/web/javascript/reference/global_objects/generatorfunction/index.md +++ b/files/en-us/web/javascript/reference/global_objects/generatorfunction/index.md @@ -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")}}_. diff --git a/files/en-us/web/javascript/reference/global_objects/generatorfunction/prototype/index.md b/files/en-us/web/javascript/reference/global_objects/generatorfunction/prototype/index.md new file mode 100644 index 000000000000000..af1991ee5c87fe6 --- /dev/null +++ b/files/en-us/web/javascript/reference/global_objects/generatorfunction/prototype/index.md @@ -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)