Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove all @@notation in JS prose #34817

Merged
merged 2 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions files/en-us/web/javascript/data_structures/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,17 @@ The [primitive coercion](https://tc39.es/ecma262/multipage/abstract-operations.h
- The [`+`](/en-US/docs/Web/JavaScript/Reference/Operators/Addition) operator — if one operand is a string, string concatenation is performed; otherwise, numeric addition is performed.
- The [`==`](/en-US/docs/Web/JavaScript/Reference/Operators/Equality) operator — if one operand is a primitive while the other is an object, the object is converted to a primitive value with no preferred type.

This operation does not do any conversion if the value is already a primitive. Objects are converted to primitives by calling its [`[@@toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive) (with `"default"` as hint), `valueOf()`, and `toString()` methods, in that order. Note that primitive conversion calls `valueOf()` before `toString()`, which is similar to the behavior of [number coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion) but different from [string coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion).
This operation does not do any conversion if the value is already a primitive. Objects are converted to primitives by calling its [`[Symbol.toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive) (with `"default"` as hint), `valueOf()`, and `toString()` methods, in that order. Note that primitive conversion calls `valueOf()` before `toString()`, which is similar to the behavior of [number coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion) but different from [string coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion).

The `[@@toPrimitive]()` method, if present, must return a primitive — returning an object results in a {{jsxref("TypeError")}}. For `valueOf()` and `toString()`, if one returns an object, the return value is ignored and the other's return value is used instead; if neither is present, or neither returns a primitive, a {{jsxref("TypeError")}} is thrown. For example, in the following code:
The `[Symbol.toPrimitive]()` method, if present, must return a primitive — returning an object results in a {{jsxref("TypeError")}}. For `valueOf()` and `toString()`, if one returns an object, the return value is ignored and the other's return value is used instead; if neither is present, or neither returns a primitive, a {{jsxref("TypeError")}} is thrown. For example, in the following code:

```js
console.log({} + []); // "[object Object]"
```

Neither `{}` nor `[]` have a `[@@toPrimitive]()` method. Both `{}` and `[]` inherit `valueOf()` from {{jsxref("Object.prototype.valueOf")}}, which returns the object itself. Since the return value is an object, it is ignored. Therefore, `toString()` is called instead. [`{}.toString()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) returns `"[object Object]"`, while [`[].toString()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString) returns `""`, so the result is their concatenation: `"[object Object]"`.
Neither `{}` nor `[]` have a `[Symbol.toPrimitive]()` method. Both `{}` and `[]` inherit `valueOf()` from {{jsxref("Object.prototype.valueOf")}}, which returns the object itself. Since the return value is an object, it is ignored. Therefore, `toString()` is called instead. [`{}.toString()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) returns `"[object Object]"`, while [`[].toString()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString) returns `""`, so the result is their concatenation: `"[object Object]"`.

The `[@@toPrimitive]()` method always takes precedence when doing conversion to any primitive type. Primitive conversion generally behaves like number conversion, because `valueOf()` is called in priority; however, objects with custom `[@@toPrimitive]()` methods can choose to return any primitive. {{jsxref("Date")}} and {{jsxref("Symbol")}} objects are the only built-in objects that override the `[@@toPrimitive]()` method. [`Date.prototype[@@toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/@@toPrimitive) treats the `"default"` hint as if it's `"string"`, while [`Symbol.prototype[@@toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/@@toPrimitive) ignores the hint and always returns a symbol.
The `[Symbol.toPrimitive]()` method always takes precedence when doing conversion to any primitive type. Primitive conversion generally behaves like number conversion, because `valueOf()` is called in priority; however, objects with custom `[Symbol.toPrimitive]()` methods can choose to return any primitive. {{jsxref("Date")}} and {{jsxref("Symbol")}} objects are the only built-in objects that override the `[Symbol.toPrimitive]()` method. [`Date.prototype[Symbol.toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/@@toPrimitive) treats the `"default"` hint as if it's `"string"`, while [`Symbol.prototype[Symbol.toPrimitive]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/@@toPrimitive) ignores the hint and always returns a symbol.

### Numeric coercion

Expand All @@ -259,11 +259,11 @@ All data types, except Null, Undefined, and Symbol, have their respective coerci

As you may have noticed, there are three distinct paths through which objects may be converted to primitives:

- [Primitive coercion](#primitive_coercion): `[@@toPrimitive]("default")` → `valueOf()` → `toString()`
- [Numeric coercion](#numeric_coercion), [number coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion), [BigInt coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#bigint_coercion): `[@@toPrimitive]("number")` → `valueOf()` → `toString()`
- [String coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion): `[@@toPrimitive]("string")` → `toString()` → `valueOf()`
- [Primitive coercion](#primitive_coercion): `[Symbol.toPrimitive]("default")` → `valueOf()` → `toString()`
- [Numeric coercion](#numeric_coercion), [number coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion), [BigInt coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#bigint_coercion): `[Symbol.toPrimitive]("number")` → `valueOf()` → `toString()`
- [String coercion](/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion): `[Symbol.toPrimitive]("string")` → `toString()` → `valueOf()`

In all cases, `[@@toPrimitive]()`, if present, must be callable and return a primitive, while `valueOf` or `toString` will be ignored if they are not callable or return an object. At the end of the process, if successful, the result is guaranteed to be a primitive. The resulting primitive is then subject to further coercions depending on the context.
In all cases, `[Symbol.toPrimitive]()`, if present, must be callable and return a primitive, while `valueOf` or `toString` will be ignored if they are not callable or return an object. At the end of the process, if successful, the result is guaranteed to be a primitive. The resulting primitive is then subject to further coercions depending on the context.

## See also

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ function* makeRangeIterator(start = 0, end = Infinity, step = 1) {

An object is **iterable** if it defines its iteration behavior, such as what values are looped over in a {{jsxref("Statements/for...of", "for...of")}} construct. Some built-in types, such as {{jsxref("Array")}} or {{jsxref("Map")}}, have a default iteration behavior, while other types (such as {{jsxref("Object")}}) do not.

In order to be **iterable**, an object must implement the **@@iterator** method. This means that the object (or one of the objects up its [prototype chain](/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)) must have a property with a {{jsxref("Symbol.iterator")}} key.
In order to be **iterable**, an object must implement the `[Symbol.iterator]()` method. This means that the object (or one of the objects up its [prototype chain](/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)) must have a property with a {{jsxref("Symbol.iterator")}} key.

It may be possible to iterate over an iterable more than once, or only once. It is up to the programmer to know which is the case.

Iterables which can iterate only once (such as Generators) customarily return `this` from their **@@iterator** method, whereas iterables which can be iterated many times must return a new iterator on each invocation of **@@iterator**.
Iterables which can iterate only once (such as Generators) customarily return `this` from their `[Symbol.iterator]()` method, whereas iterables which can be iterated many times must return a new iterator on each invocation of `[Symbol.iterator]()`.

```js
function* makeIterator() {
Expand All @@ -117,10 +117,10 @@ for (const itItem of iter) {
console.log(iter[Symbol.iterator]() === iter); // true

// This example show us generator(iterator) is iterable object,
// which has the @@iterator method return the `iter` (itself),
// which has the [Symbol.iterator]() method return the `iter` (itself),
// and consequently, the it object can iterate only _once_.

// If we change the @@iterator method of `iter` to a function/generator
// If we change the [Symbol.iterator]() method of `iter` to a function/generator
// which returns a new iterator/generator object, `iter`
// can iterate many times

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Here are some things you may expect when extending a class:
However, the above expectations take non-trivial efforts to implement properly.

- The first one requires the static method to read the value of [`this`](/en-US/docs/Web/JavaScript/Reference/Operators/this) to get the constructor for constructing the returned instance. This means `[p1, p2, p3].map(Promise.resolve)` throws an error because the `this` inside `Promise.resolve` is `undefined`. A way to fix this is to fall back to the base class if `this` is not a constructor, like {{jsxref("Array.from()")}} does, but that still means the base class is special-cased.
- The second one requires the instance method to read [`this.constructor`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) to get the constructor function. However, `new this.constructor()` may break legacy code, because the `constructor` property is both writable and configurable and is not protected in any way. Therefore, many copying built-in methods use the constructor's [`@@species`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/species) property instead (which by default just returns `this`, the constructor itself). However, `@@species` allows running arbitrary code and creating instances of arbitrary type, which poses a security concern and greatly complicates subclassing semantics.
- The second one requires the instance method to read [`this.constructor`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) to get the constructor function. However, `new this.constructor()` may break legacy code, because the `constructor` property is both writable and configurable and is not protected in any way. Therefore, many copying built-in methods use the constructor's [`[Symbol.species]`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/species) property instead (which by default just returns `this`, the constructor itself). However, `[Symbol.species]` allows running arbitrary code and creating instances of arbitrary type, which poses a security concern and greatly complicates subclassing semantics.
- The third one leads to visible invocations of custom code, which makes a lot of optimizations harder to implement. For example, if the `Map()` constructor is called with an iterable of _x_ elements, then it must visibly invoke the `set()` method _x_ times, instead of just copying the elements into the internal storage.

These problems are not unique to built-in classes. For your own classes, you will likely have to make the same decisions. However, for built-in classes, optimizability and security are a much bigger concern. New built-in methods always construct the base class and call as few custom methods as possible. If you want to subclass built-ins while achieving the above expectations, you need to override all methods that have the default behavior baked into them. Any addition of new methods on the base class may also break the semantics of your subclass because they are inherited by default. Therefore, a better way to extend built-ins is to use [_composition_](#avoiding_inheritance).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TypeError: String.prototype.replaceAll argument must not be a non-global regular

The {{jsxref("String.prototype.matchAll()")}} and {{jsxref("String.prototype.replaceAll()")}} methods require a {{jsxref("RegExp")}} object with the {{jsxref("RegExp/global", "global")}} flag set. This flag indicates that the regular expression can match all locations of the input string, instead of stopping at the first match. Although the `g` flag is redundant when using these methods (because these methods always do a global replacement), they are still required to make the intention clear.

It's worth noting that the `g` flag validation is done in the `matchAll` and `replaceAll` methods. If you use the [`@@matchAll`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll) method of `RegExp` instead, you won't get this error, but there will only be a single match.
It's worth noting that the `g` flag validation is done in the `matchAll` and `replaceAll` methods. If you use the [`[Symbol.matchAll]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll) method of `RegExp` instead, you won't get this error, but there will only be a single match.

## Examples

Expand All @@ -54,7 +54,7 @@ const newPattern = new RegExp(
"abc".replaceAll(newPattern, "f"); // "fff"
```

If you only intend to do a single matching/replacement: use {{jsxref("String.prototype.match()")}} or {{jsxref("String.prototype.replace()")}} instead. You can also use the `@@matchAll` method if you want an iterator like `matchAll` returns that only contains one match, but doing so will be very confusing.
If you only intend to do a single matching/replacement: use {{jsxref("String.prototype.match()")}} or {{jsxref("String.prototype.replace()")}} instead. You can also use the `[Symbol.matchAll]()` method if you want an iterator like `matchAll` returns that only contains one match, but doing so will be very confusing.

```js example-good
"abc".match(/./); // [ "a" ]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: arguments[@@iterator]()
title: arguments[Symbol.iterator]()
slug: Web/JavaScript/Reference/Functions/arguments/@@iterator
page-type: javascript-instance-method
browser-compat: javascript.functions.arguments.@@iterator
---

{{jsSidebar("Functions")}}

The **`[@@iterator]()`** method of {{jsxref("Functions/arguments", "arguments")}} objects implements the [iterable protocol](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) and allows `arguments` objects to be consumed by most syntaxes expecting iterables, such as the [spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) and {{jsxref("Statements/for...of", "for...of")}} loops. It returns an [array iterator object](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) that yields the value of each index in the `arguments` object.
The **`[Symbol.iterator]()`** method of {{jsxref("Functions/arguments", "arguments")}} objects implements the [iterable protocol](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) and allows `arguments` objects to be consumed by most syntaxes expecting iterables, such as the [spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) and {{jsxref("Statements/for...of", "for...of")}} loops. It returns an [array iterator object](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) that yields the value of each index in the `arguments` object.

The initial value of this property is the same function object as the initial value of the {{jsxref("Array.prototype.values")}} property (and also the same as [`Array.prototype[@@iterator]`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator)).
The initial value of this property is the same function object as the initial value of the {{jsxref("Array.prototype.values")}} property (and also the same as [`Array.prototype[Symbol.iterator]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator)).

## Syntax

Expand All @@ -29,7 +29,7 @@ The same return value as {{jsxref("Array.prototype.values()")}}: a new [iterable

### Iteration using for...of loop

Note that you seldom need to call this method directly. The existence of the `@@iterator` method makes `arguments` objects [iterable](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol), and iterating syntaxes like the `for...of` loop automatically call this method to obtain the iterator to loop over.
Note that you seldom need to call this method directly. The existence of the `[Symbol.iterator]()` method makes `arguments` objects [iterable](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol), and iterating syntaxes like the `for...of` loop automatically call this method to obtain the iterator to loop over.

```js
function f() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ console.log(midpoint(3, 1, 4, 1, 5)); // 3
- : Reference to the currently executing function that the arguments belong to. Forbidden in strict mode.
- {{jsxref("Functions/arguments/length", "arguments.length")}}
- : The number of arguments that were passed to the function.
- {{jsxref("Functions/arguments/@@iterator", "arguments[@@iterator]")}}
- [`arguments[Symbol.iterator]()`](/en-US/docs/Web/JavaScript/Reference/Functions/arguments/@@iterator)
- : Returns a new {{jsxref("Array/@@iterator", "Array iterator", "", 0)}} object that contains the values for each index in `arguments`.

## Examples
Expand Down
Loading