Array.prototype.some()を学ぶ

今回はsomeです！
早速[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)を見ていきます

> some() は Array インスタンスのメソッドで、指定された関数で実装されているテストに、配列の中の少なくとも 1つの要素が合格するかどうかを判定します。配列の中で指定された関数が true を返す要素を見つけた場合は true を返し、そうでない場合は false を返します。配列は変更しません。

１つでも当てはまればtrueを返してくれます。
下記を見ると、確かに当てはまるものがあればtrueを返しています。
```js
// 公式から引用
const array = [1, 2, 3, 4, 5];
const even = (element) => element % 2 === 0;
console.log(array.some(even)); // true

// falseを試す
const array2 = [1, 3, 5];
const even2 = (element) => element % 2 === 0;
console.log(array2.some(even2)); // false
```

## 構文、引数

some(callbackFn)
some(callbackFn, thisArg)

#### callbackFn

お馴染みの3つを引数を持つことができます。

> element
配列内で処理中の現在の要素です。
index
配列内で処理中の現在の要素のインデックスです。
array
some() が呼び出された配列です。

#### thisArg
何をthisとして扱うかを指定できます。

## 返値
> 配列の要素のいずれかで callbackFn が真値を返した場合は、直ちに true を返します。それ以外の場合は false です。

`直ちに true を返します` 
確かに、1つの要素が合格するかどうかを判定するので、全部見る必要ないですよね。

## 解説

> callbackFn は値が割り当てられている配列インデックスに対してのみ呼び出されます。疎配列の空のスロットに対しては呼び出されません。

疎配列の時はskipしてくるようです
確認してみます。

```js
const array = [1,,,, 3, 4, 5, 7, 9];
const even = (element , index) => {
  console.log(element);
  console.log(index);
  console.log("-----------");
  return element % 2 === 0;
};
console.log(array.some(even));
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/c89e74c1-4570-48f8-9bd7-bf82a81f9007.png" width="200">

1のあと、index番号3である、4を見にいっています。
疎配列はskipしてくれました！！

#### undefinedやnull

undefinedやnullが入るとどうなるんでしょうか?

```js
// undefinedを入れてみる
const array = [1,,, 3, 5, 7, undefined];
const even = (element , index) => {
  console.log(index);
  console.log("-----------");
  return element % 2 === 0;
};
console.log(array.some(even));
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/b2482574-6147-c7ca-e8ac-81703dc66bd2.png" width="200">

undefinedだとfalseですね！期待通りの動きをしました。


```js
// nullを入れてみる
const array = [1,,, 3, 5, 7, null];
const even = (element , index) => {
  console.log(index);
  console.log("-----------");
  return element % 2 === 0;
};
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/3d76edc8-f15f-e5e0-9c15-cc3aacf69d06.png" width="200">

え？なんでtrue返ってくるの？

```js
const array = [1, 3, 5, null];
const even = (element) => element % 2 === 0;
console.log(array.some(even));

console.log(null % 2) // あなた何？
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/342e2188-4fea-3813-de02-9062d74afbe4.png" width="100">

なるほど、null%2 は0だからですね！(:frowning2:)ｳｵｰ

<b>計算するものに対してsomeを使うと予期せぬ問題起こりそう</b>です。

```js
const array = [1, 3, 5, null];
const even = (element) => {
  if(element === null) return false // falseにして！
  return element % 2 === 0
};
console.log(array.some(even));
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/eb62306a-3939-d3d5-a6fe-34269684cc06.png" width="200">

あぶねぇ！気をつけます。。。
*`if(!element) return false` とすると、0もfalseとして扱われるので注意です。

では続きを。

> callbackFn は、 some() の呼び出しを始めたときの配列の長さを超えて追加された要素にはアクセスしません。
既に処理したインデックスを変更しても、 callbackFn が再度呼び出されることはありません。
まだ処理していない既存の配列要素が callbackFn によって変更された場合、callbackFn に渡される値はその要素が取得された時点での値になります。削除された要素は処理されません。

すでに処理したものは影響なし。
未来で処理するものは影響する...。

ちょっと怖いので検証します。

```js
let array = [1, 2, 3, 4, 5];

const sample = (element, index, arr) => {
  // 既に処理したインデックスの値を変更（影響しない）
  if (index === 0) {
    arr[0] = 99;
  }

  // 未処理のインデックスの値を変更（影響する : 未処理に値に変更を加えたため）
  if (index === 2) {
    arr[3] = 100;
  }

  // 配列に新しい要素を追加（影響しない : 呼び出しを始めたときの配列の長さを超えたため！）
  if (index === 3) {
    arr.push(4);
  }

  // 4を追加してみる : (影響しない : 未処理に値に変更を加えたため )
  if (index === 5) {
    arr.push(4);
  }
  return element === 4;
};

console.log(array.some(sample)) // false : 4だったものが100になってしまったため。
console.log(array); // [99, 2, 3, 100, 5, 4] 
```

未来の処理を書き換えると結果がわかる。
some中に値をpushしても、なにも影響しない。
ここはハマりそうなので、検証しておいて良かったです。


## 例 : ある値が配列に存在するかどうかのチェック

テキスト一致も大丈夫ですね。

```js
// 公式から引用
const fruits = ["apple", "banana", "mango", "guava"];

function checkAvailability(arr, val) {
  return arr.some((arrVal) => val === arrVal);
}

checkAvailability(fruits, "kela"); // false
checkAvailability(fruits, "banana"); // true
```

-----

今回はsomeを見ていきました！
一致していたら〜の処理はよく使うので、仕様を確認しておいて良かったです。
some次は、everyを見ておいた方がいいですね！

次回はeveryです！