---
tags: 如何正確使用字串, 字串 or 陣列處理方法, string, 陣列, array, indexOf, lastIndexOf, includes, 嚴格相等比較, SameValueZero, SameValueNonNumeric, searchElement, search
---
尋找是否包含某元素:includes、indexOf
===
:::spoiler 目錄
- includes、indexOf
- indexOf
- 參數
- 範例
- 搜索空字串
- 參數 position 是負值
- 文字
- 陣列
- 從後面往前找:lastIndexOf
- 參數
- 範例
- 與 indexOf 的不同
- search
- includes
- 範例
- indexOf 與 includes 的差異
- 回傳值
- 關於 NaN 的問題
- 關於空陣列的問題
- 嚴格相等比較 vs. SameValueZero
- 嚴格相等比較
- SameValueZero
- 元素型別為 Object 時,需要考慮值的參考
:::
<br/>
返回新的值,++不會更改原始的值++。
includes、indexOf
---
| | 過去 | ES7 |
| -------- | -------- | -------- |
| 尋找是否包含某元素 | ++indexOf++ | ++includes++ |
| | ++lastIndexOf++ | |
尋找陣列中是否包含某元素,過去使用 indexOf 處理,現在 ES7 有 includes 可以使用。
假若比對的是字串,可以使用 match、search,詳細見:[尋找比對字串:match、search](https://hackmd.io/wk6ELp3pTSujIwf8yDlFjQ?view)。
indexOf
---
回傳元素於 **陣列 / 字串** 中第一個被找到之**索引**,若不存在於陣列 / 字串中則回傳 -1。
### Ⅰ. 參數
> indexOf ( searchString [ , fromIndex] )
- searchElement:選填,判斷的值,預設為 `undefined`。
- fromIndex:選填,從哪個位置開始判斷,預設為 0。
:::spoiler 如果<u>未搜尋成功,返回 -1</u>。
```jsx
"0123".indexOf("A"); // -1
"0123".indexOf("1",99); // -1
[2, 9, 9].indexOf(7); // -1
[2, 9, 9].indexOf(2, 1); // -1
```
:::
:::spoiler 參數 searchString <u>沒有指定,默認搜尋的是 `undefined`</u>。
```jsx
"0123".indexOf(); // -1
'undefined'.indexOf(); // 0
[2, 9, 9].indexOf(); // -1
[undefined].indexOf(); // 0
```
:::
:::spoiler 參數 searchString 區分大小寫。
```jsx
let string = "Hello World!";
string.indexOf("h"); // -1
string.indexOf("H"); // 0
```
:::
### Ⅱ. 範例
```jsx
let string = "Hello World!";
string.indexOf("!"); // 11
string.indexOf("!",11); // 11
```
```jsx
let array = [2, 9, 9];
array.indexOf(2); // 0
array.indexOf(9, 2); // 2
```
> [Dome](https://codepen.io/betty-hu/pen/NWXeJeV)
### Ⅲ. 搜索空字串
搜索空字串,假若 fromIndex 參數小於字串長度,結果將是 fromIndex 的值。反之,將會是字串長度。
:::spoiler 沒有 fromIndex 參數的情況,返回 0。
```jsx
"0123".indexOf(""); // 0
```
:::
:::spoiler 參數 fromIndex 小於字串長度,返回 fromIndex 的值。
```jsx
"0123".indexOf("",1); // 1
```
▲ ( fromIndex 參數 = 1 ) < (字串長度 = 4) → 返回 fromIndex 的值 = 1
:::
:::spoiler 參數 fromIndex 大於字串長度,返回字串長度。
```jsx
"0123".indexOf("",99); // 4
```
▲ ( fromIndex 參數 = 99 ) > (字串長度 = 4) → 返回字串長度 = 4
:::
:::spoiler 假若對象是陣列的話,返回 -1。
```jsx
[0,1,2,3].indexOf("",1); // -1
```
:::
### Ⅳ. 參數 fromIndex 是負值
#### Ⅳ-1. 文字
參數 fromIndex 是負值,假若是文字,將會視作為 0,也就是搜索全部。
```jsx
"Hello World!".indexOf("World",-1); // 6
```
#### Ⅳ-2. 陣列
參數 fromIndex 是負值,假若是陣列,從後方往前計算。
最後一個的索引值是 -1,也就是說 fromIndex = -1,等於最後一項,以此類推。
```jsx
["Hello", "World", "!"].indexOf("!",-1); // 2
["Hello", "World", "!"].indexOf("World",-1); // -1
["Hello", "World", "!"].indexOf("World",-2); // 1
```
### Ⅴ. 從後面往前找:lastIndexOf
與 indexOf 相同,但是從後面往前找。
#### Ⅰ.參數
> lastIndexOf ( searchElement [ , fromIndex ] )
- searchElement:選填,判斷的值,預設為 `undefined`。
- fromIndex:選填,從哪個位置開始判斷,預設為最後一項。
#### Ⅱ. 範例
```jsx
"Hello World!".lastIndexOf("!"); // 11
"Hello World!".lastIndexOf("!",10); // -1
```
> [Dome](https://codepen.io/betty-hu/pen/bGQOMLV?editors=0012#_=_)
#### Ⅲ. 與 indexOf 的不同
```jsx
"abcabc".lastIndexOf("a"); // 3
"abcabc".lastIndexOf("a",5); // 3
"abcabc".indexOf("a"); // 0
"abcabc".lastIndexOf("a",0); // 0
```
▲ fromIndex 預設最後一項。
```jsx
"abcabc".indexOf(""); // 0
"abcabc".lastIndexOf(""); // 6
```
▲ 搜索空字串:沒有 fromIndex 參數的情況,返回字串長度。
```jsx
"abcabc".indexOf("c",-3); // 2 (負數視作搜尋全部)
"abcabc".lastIndexOf("c",-3); // -1
```
▲ 參數 fromIndex 是負值,假若是文字,將會回傳 -1。
### Ⅵ. search
> str . search ( regexp )
```jsx
/* 沒有使用正規表達式,僅使用字串搜尋 */
'some text'.search('text') // 0
'some text'.search('TEXT') // -1
/* 使用正規表達式 */
'some text'.search(/TEXT/i) // 0
```
找出字串在另一字串中的位置,有找到回傳字串的起始位置,沒找到回傳 -1。
跟 `indexOf()` 相同都是尋找並回傳位置,只是 `search()` 可以用正規表示式當參數,且只能作用在字串上,不能用於陣列。詳細見:[尋找比對字串:match、search](https://hackmd.io/wk6ELp3pTSujIwf8yDlFjQ?view)
includes
---
ES7 提供的新函式。直接回傳是否包含該元素的 Boolean 值,true 代表包含、false 代表不包含。
#### 參數
> includes ( searchElement [ , fromIndex] )
- searchElement:選填,判斷的值,預設為 undefined。
- fromIndex:選填,從哪個位置開始判斷,預設為 0。
用法同 indexOf。
#### Ⅰ. 範例
```jsx
'JS ECMA TC39'.includes('ECMA'); // true
['JS', 'ECMA', 'TC39'].includes('ECMA'); // true
['JS ECMA TC39'].includes('ECMA'); // false
/* searchElement 預設 */
"undefined".includes(); // true
[undefined].includes(); // true
/* fromIndex 參數 */
"abcdef".includes("c",3); // false
"abcdef".includes("c",-3); // true
['JS', 'ECMA', 'TC39'].includes('ECMA', 1); // true
['JS', 'ECMA', 'TC39'].includes('ECMA', -1); // false
/* 搜索空字串 */
"abcdef".includes(""); // true
[00,11,22].includes(""); // false
```
> [Dome](https://codepen.io/betty-hu/pen/zYMeRRM?editors=0012)
indexOf 與 includes 的差異
---
### 回傳值
- indexOf:回傳元素於 陣列 / 字串 中第一個被找到之索引。
- includes:回傳是否包含該元素的 Boolean 值。
```jsx
['JS', 'ECMA', 'TC39'].indexOf('ECMA'); // 1
['JS', 'ECMA', 'TC39'].indexOf('ECMA') == true // true
['JS', 'ECMA', 'TC39'].indexOf('ECMA') !== -1 // true
['JS', 'ECMA', 'TC39'].includes('ECMA'); // true
```
### 關於 NaN 的問題
- indexOf:使用嚴格相等比較,而 NaN !== NaN,無法在陣列中找到 NaN。
- includes:使用 searchElement 演算法,可以解決 NaN 的問題。
```jsx
[NaN].indexOf(NaN) !== -1 // false
[NaN].includes(NaN) // true
```
### 關於空陣列的問題
- indexOf:遇到空陣列會直接跳過,繼續比對下個元素,無法在陣列中找到空陣列。
- includes:不會跳過空陣列,而是視為 `undefined`,因此能夠捕抓空陣列。
```jsx
// Array(3) = [ , , ]
Array(3).indexOf() !== -1 // false
Array(3).includes() // true
```
嚴格相等比較 vs. SameValueZero
---
indexOf 採用嚴格相等比較;includes 採用 SameValueZero。
### ++嚴格相等比較++
1. 比較型別是否相同,不同就回傳 false。
2. 型別是 Number 或 BigInt ,**進行值的比較**。在值的比較中,++值是 NaN 回傳 false,這是 indexOf 中 NaN 不等於 NaN 的原因++。
3. 其他型別使用 SameValueNonNumeric 演算法。
:::spoiler 補充:SameValueNonNumeric 演算法
- 值為 null 或 undefined,回傳 true。
- String、Boolean、Symbol、Object 型別比較值是否相同。
:::
### ++SameValueZero++
1. 比較型別是否相同,不同就回傳 false。
2. 型別是 Number 或 BigInt ,**進行 Type(x)::sameValueZero(x, y) 的比較**。++兩方的值是 NaN,回傳 true,這是 includes 能夠解決 NaN 不等於 NaN 的原因++。
3. 其他型別使用 SameValueNonNumeric 演算法。
:::spoiler 補充:`Type(x)::sameValueZero(x, y)`
- `Type(x)::sameValueZero(x, y)`:每種內建型別定義許多 operations,而 Number、BigInt 是 ECMAScript 內建的 Numeric 型別,其中的 operations 是 T::sameValueZero(x, y)。
- 兩方的值是 NaN,回傳 true,這是 includes 能夠解決 NaN 不等於 NaN 的原因。
:::
元素型別為 Object 時,需要考慮值的參考
---
元素型別為 Object,值相同但參考不同,indexOf 和 includes 回傳 false。
```jsx
let array = [{id: 1}, {id: 2}, {id: 3}];
/* 值相同,但參考不同 */
array.indexOf({id: 2}) !== -1 // false
array.includes({id: 2}) // false
```
```jsx
let item = {id: 2};
let array = [{id: 1}, item, {id: 3}];
/* 值相同、參考相同 */
array.indexOf(item) !== -1 // true
array.includes(item) // true
```