You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 17, 2020. It is now read-only.
This proposal is officially in stage 1 of [the TC39 process](https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit); the author believes it is ready to advance to stage 2, but has not yet had time to present to the committee.
6
6
7
-
However, its further advancement is blocked by the fact that [it is not web-compatible](http://esdiscuss.org/topic/having-a-non-enumerable-array-prototype-contains-may-not-be-web-compatible). There are [thoughts](http://esdiscuss.org/topic/array-prototype-contains-solutions)of how we could work toward a solution, but nothing is clear yet.
7
+
This proposal was formerly for `Array.prototype.contains`, but that name [is not web-compatible](http://esdiscuss.org/topic/having-a-non-enumerable-array-prototype-contains-may-not-be-web-compatible). Per the November 2014 TC39 meeting, the name of both `String.prototype.contains` and `Array.prototype.contains` was changed to `includes` to dodge that bullet.
8
8
9
9
## Motivation
10
10
11
-
When using ECMAScript arrays, it is commonly desired to determine if the array contains an element. The prevailing pattern for this is
11
+
When using ECMAScript arrays, it is commonly desired to determine if the array includes an element. The prevailing pattern for this is
12
12
13
13
```js
14
14
if (arr.indexOf(el) !==-1) {
@@ -20,44 +20,44 @@ with various other possibilities, e.g. `arr.indexOf(el) >= 0`, or even `~arr.ind
20
20
21
21
These patterns exhibit two problems:
22
22
23
-
- They fail to "say what you mean": instead of asking about whether the array contains an element, you ask what the index of the first occurrence of that element in the array is, and then compare it or bit-twiddle it, to determine the answer to your actual question.
23
+
- They fail to "say what you mean": instead of asking about whether the array includes an element, you ask what the index of the first occurrence of that element in the array is, and then compare it or bit-twiddle it, to determine the answer to your actual question.
24
24
- They fail for `NaN`, as `indexOf` uses Strict Equality Comparison and thus `[NaN].indexOf(NaN) === -1`.
25
25
26
26
## Proposed Solution
27
27
28
-
We propose the addition of an `Array.prototype.contains` method, such that the above patterns can be rewritten as
28
+
We propose the addition of an `Array.prototype.includes` method, such that the above patterns can be rewritten as
29
29
30
30
```js
31
-
if (arr.contains(el)) {
31
+
if (arr.includes(el)) {
32
32
...
33
33
}
34
34
```
35
35
36
-
This has almost the same semantics as the above, except that it uses the SameValueZero comparison algorithm instead of Strict Equality Comparison, thus making `[NaN].contains(NaN)` true.
36
+
This has almost the same semantics as the above, except that it uses the SameValueZero comparison algorithm instead of Strict Equality Comparison, thus making `[NaN].includes(NaN)` true.
37
37
38
38
Thus, this proposal solves both problems seen in existing code.
39
39
40
-
We additionally add a `fromIndex` parameter, similar to `Array.prototype.indexOf` and `String.prototype.contains`, for consistency.
40
+
We additionally add a `fromIndex` parameter, similar to `Array.prototype.indexOf` and `String.prototype.includes`, for consistency.
41
41
42
42
## FAQs
43
43
44
-
### Why `contains` instead of `has`?
44
+
### Why `includes` instead of `has`?
45
45
46
-
If you survey existing APIs, `has` is used for conceptual "keys," whereas `contains` is used for conceptual "values." That is:
46
+
If you survey existing APIs, `has` is used for conceptual "keys," whereas `includes` is used for conceptual "values." That is:
47
47
48
48
- Keys inside a key-value map: `Map.prototype.has(key)`, `WeakMap.prototype.has(key)`, `Reflect.has(target, propertyKey)`
49
49
- Sets, whose elements are conceptually both keys and values: `Set.prototype.has(value)`, `WeakSet.prototype.has(value)`, `Reflect.Loader.prototype.has(name)`
50
-
- Strings, which are conceptually maps from indices to code points: `String.prototype.contains(searchString, position)`
50
+
- Strings, which are conceptually maps from indices to code points: `String.prototype.includes(searchString, position)`
51
51
52
52
The best consistency here is with `String`, not with `Map` or `Set`.
53
53
54
-
Finally, the web has classes like [DOMStringList](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringList) and [DOMTokenList](http://dom.spec.whatwg.org/#interface-domtokenlist) which are array-like, and have methods named `contains` with the same semantics. Meshing with those, and in the case of `DOMStringList` potentially replacing them, is a nice side benefit.
54
+
The web has classes like [DOMStringList](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringList) and [DOMTokenList](http://dom.spec.whatwg.org/#interface-domtokenlist) which are array-like, and have methods named `contains` with the same semantics as our `includes`. Unfortunately, meshing with those is not web-compatible, as explained above; we will have to accept this inconsistency.
55
55
56
-
### But `String.prototype.contains` works on strings, not characters!?
56
+
### But `String.prototype.includes` works on strings, not characters!?
57
57
58
-
Yes, that's true. The best way to think about this is that `String.prototype.indexOf` and `String.prototype.contains` behave like their `Array.prototype` counterparts in the special case of a single character. But the string versions can also be used in the more general case of a larger string.
58
+
Yes, that's true. The best way to think about this is that `String.prototype.indexOf` and `String.prototype.includes` behave like their `Array.prototype` counterparts in the special case of a single character. But the string versions can also be used in the more general case of a larger string.
59
59
60
-
So in this way, the relationship between `String.prototype.contains` and `Array.prototype.contains` is the same as the relationship between `String.prototype.indexOf` and `Array.prototype.indexOf`.
60
+
So in this way, the relationship between `String.prototype.includes` and `Array.prototype.includes` is the same as the relationship between `String.prototype.indexOf` and `Array.prototype.indexOf`.
61
61
62
62
### Why SameValueZero?
63
63
@@ -72,21 +72,21 @@ There are four equality algorithms in the current ES6 draft:
72
72
73
73
Using Abstract Equality Comparison would be bonkers, of course. Using SameValue is not a good idea for the same reasons it is not used by `Map` and `Set`. (Briefly: `-0`s can sneak into your code fairly easily via arithmetic operations, but you almost always desire `-0` to be treated the same as `+0`, so distinguishing them will just cause spurious failures.) This leaves Strict Equality Comparison and SameValueZero as the two possibilities.
74
74
75
-
SameValueZero is generally the better choice, as it allows you to detect if an array contains a `NaN`. The argument for Strict Equality Comparison boils down to "bug compatibility" with `Array.prototype.indexOf`. But one of the purposes of `Array.prototype.contains` is to steer users away from creating these sort of bugs.
75
+
SameValueZero is generally the better choice, as it allows you to detect if an array includes a `NaN`. The argument for Strict Equality Comparison boils down to "bug compatibility" with `Array.prototype.indexOf`. But one of the purposes of `Array.prototype.includes` is to steer users away from creating these sort of bugs.
76
76
77
-
This introduces a slight refactoring hazard from `Array.prototype.indexOf` to `Array.prototype.contains`: they will indeed behave differently for arrays containing `NaN`s. However, it seems much more likely that code will become _less_ buggy via this refactoring, instead of causing problems. Introducing a new method, and accompanying it with the appropriate messaging around this case, should help.
77
+
This introduces a slight refactoring hazard from `Array.prototype.indexOf` to `Array.prototype.includes`: they will indeed behave differently for arrays containing `NaN`s. However, it seems much more likely that code will become _less_ buggy via this refactoring, instead of causing problems. Introducing a new method, and accompanying it with the appropriate messaging around this case, should help.
NOTE `contains` compares _searchElement_ to the elements of the array, in ascending order, using the SameValueZero algorithm, and if found at any position, returns **true**; otherwise, **false** is returned.
3
+
NOTE `includes` compares _searchElement_ to the elements of the array, in ascending order, using the SameValueZero algorithm, and if found at any position, returns **true**; otherwise, **false** is returned.
4
4
5
5
The optional second argument _fromIndex_ defaults to 0 (i.e. the whole array is searched). If it is greater than or equal to the length of the array, **false** is returned, i.e. the array will not be searched. If it is negative, it is used as the offset from the end of the array to compute _fromIndex_. If the computed index is less than 0, the whole array will be searched.
6
6
7
-
When the `contains` method is called, the following steps are taken:
7
+
When the `includes` method is called, the following steps are taken:
8
8
9
9
1. Let _O_ be the result of calling ToObject passing the **this** value as the argument.
10
10
1. ReturnIfAbrupt(_O_).
@@ -26,4 +26,4 @@ When the `contains` method is called, the following steps are taken:
26
26
1. Increase _k_ by 1.
27
27
1. Return **false**.
28
28
29
-
The `length` property of the `contains` method is **1**.
29
+
The `length` property of the `includes` method is **1**.
0 commit comments