every() は全部が満たすか、some() は1つでも満たすかを true / false で返します。空配列で答えが逆になること、途中で止まること、includes() との使い分けまで実行して確かめます。
どちらも返るのは true か false だけです。要素は返りません。
example.js
const nums = [2, 4, 6];
console.log(nums.every((n) => n % 2 === 0));
console.log(nums.some((n) => n > 5));
console.log(nums.every((n) => n > 5));
console.log(nums.some((n) => n > 99));
出力書き換えて実行できます
true
true
false
false
example.js
console.log([].every((n) => n > 0));
console.log([].some((n) => n > 0));
console.log([].every(() => false));
出力書き換えて実行できます
true
false
true
| 使うもの |
意味 |
日本語にすると |
every() |
全部が満たす |
「すべて〜である」 |
some() |
1つでも満たす |
「〜が1つでもある」 |
いちばんの落とし穴:空の配列
javascript
function canSubmit(errors) {
return errors.every((error) => error.level === 'warn');
}
console.log(canSubmit([{ level: 'warn' }]));
console.log(canSubmit([]));
true
true
example.js
function canSubmit(errors) {
return errors.length > 0 && errors.every((error) => error.level === 'warn');
}
console.log(canSubmit([{ level: 'warn' }]));
console.log(canSubmit([]));
出力書き換えて実行できます
true
false
空の配列に every() を使うと、いつでも true です。
条件の中身は1度も呼ばれません。
これは間違いではなく、反例が1つも無いという意味です。
数学の「すべての〜」と同じ決まりで、空虚な真と呼ばれます。
事故になるのはこういう形です。
example.js
const seen = [];
[1, 2, 3, 4].every((n) => {
seen.push(n);
return n < 2;
});
console.log('every が見たもの:', seen.join(','));
const seen2 = [];
[1, 2, 3, 4].some((n) => {
seen2.push(n);
return n > 2;
});
console.log('some が見たもの:', seen2.join(','));
出力書き換えて実行できます
every が見たもの: 1,2
some が見たもの: 1,2,3
example.js
const list = [{ id: 1 }, { id: 2 }];
console.log(list.includes({ id: 1 }));
console.log(list.some((item) => item.id === 1));
出力書き換えて実行できます
false
true
読み込みに失敗して errors が空だったときも true になります。
「空かどうか」は別に確かめてください。
example.js
const nums = [1, 2, 3];
console.log(nums.filter((n) => n > 2).length > 0);
console.log(nums.some((n) => n > 2));
出力書き換えて実行できます
true
true
example.js
console.log([1, 2].every((n) => n));
console.log([0, 1].every((n) => n));
console.log([{}, []].some((v) => v));
console.log([''].some((v) => v));
出力書き換えて実行できます
true
false
true
false
「空なら通す」が正しい場面もあります。決めるのは仕様であって、既定の挙動ではありません。
答えが出たところで止まる
javascript
const check = async (n) => n > 100;
console.log([1, 2, 3].every(check));
console.log([1, 2, 3].some(check));
console.log(typeof check(1));
true
true
object
example.js
const check = async (n) => n > 100;
const results = await Promise.all([1, 2, 3].map(check));
console.log(results);
console.log(results.every(Boolean), results.some(Boolean));
出力書き換えて実行できます
[ false, false, false ]
false false
every() … 最初の false で止まる
some() … 最初の true で止まる
重い判定を書いても、全部は走りません。
逆に言うと、条件の中で全要素に副作用を起こす書き方は壊れます。数を数えたいなら filter().length を使ってください。
includes() との使い分け
example.js
const form = { name: 'あ', email: '' };
console.log(Object.values(form).every((value) => value !== ''));
console.log(Object.entries(form).filter(([, value]) => value === '').map(([key]) => key));
出力書き換えて実行できます
false
[ 'email' ]
example.js
['a', 'b'].every((value, index, array) => {
console.log(value, index, array.length);
return true;
});
出力書き換えて実行できます
a 0 2
b 1 2
includes() が見るのは同じ値かどうかです。
見た目が同じでも、別に作ったオブジェクトは一致しません。
中身の条件で探すなら some() です。
→ includes() / indexOf()
似ているものとの違い
| 欲しいもの |
使うもの |
返るもの |
| 全部が条件を満たすか |
every() |
true / false |
| 1つでもあるか |
some() |
true / false |
| その要素 が欲しい |
find() |
要素 or undefined |
| 条件に合うもの全部 |
filter() |
配列 |
| 何件あるか |
filter().length |
数 |
「あるかどうか」だけ知りたいのに filter() を書くと、
要らない配列を作ってから捨てることになります。
example.js
const holed = [1, , 3];
const seen = [];
holed.every((n) => {
seen.push(n);
return true;
});
console.log(seen.length, JSON.stringify(seen));
console.log(holed.some((n) => n === undefined));
出力書き換えて実行できます
2 [1,3]
false
答えは同じですが、some() は見つかった時点で止まります。
返す値は真偽値でなくてよい
返した値は真偽値として見られます。
空のオブジェクトや空の配列は true 側、0 と空文字は false 側です。
→ なぜ === を使うのか
よくある間違い:非同期の条件を渡す
どちらも true です。中身は1つも 100 を超えていません。
async を付けた関数が返すのは Promise です。
Promise は必ず真なので、every() は全部通り、some() は最初で止まります。
await を書く場所がありません。
先に全部走らせて、結果の配列で判定してください。
→ 複数の非同期処理を同時に走らせる
オブジェクトに使うとき
every() と some() は配列のものです。
オブジェクトなら、いったん配列にしてください。
「揃っているか」だけなら every()、「どれが足りないか」なら filter() です。
→ Object.keys() / values() / entries()
条件には3つ渡ってくる
使わない引数は書かなくて構いません。
穴のある配列では呼ばれない
length は3ですが、条件は2回しか呼ばれません。
undefined が入っているのとは違います。
→ 配列の穴
まとめ
- 返るのは
true / false だけ。要素は返らない
- 空の配列で
every() は true、some() は false
every() は最初の false、some() は最初の true で止まる
- 中身の条件で「あるか」を見るならincludes ではなく some
- 要素そのものが欲しいなら
find()、全部欲しいなら filter()
- 穴のある配列では条件が呼ばれない
async の条件は必ず true になる。 Promise.all() で先に走らせる