How do Array.prototype.some and Array.prototype.every short-circuit, and what does each of them return for an empty array?
answer
- stop as soon as the answer is known
- boolean out, not a list of matches
- first truthy ends one, first falsy the other
- the empty array is the trick case
- vacuous truth
basics
~20 sArray.prototype.some stops at the first element whose predicate returns truthy and yields true; every stops at the first falsy result and yields false. On an empty array some returns false and every returns true, because every is vacuously satisfied when there is nothing to violate it.
solid answer
~50 sBoth take a predicate called as `(element, index, array)` and return a boolean, but they look for opposite evidence. `some` is an existence check: it stops the moment the predicate returns truthy and returns `true`, and only returns `false` after visiting every element. `every` is a universal check: it stops at the first falsy result and returns `false`, otherwise `true`. That short-circuit is the reason to prefer them over `filter(...).length > 0`, which always scans the whole array and allocates a throwaway array. The empty-array answers surprise people: `[].some(p)` is `false` and `[].every(p)` is `true` — vacuous truth, since there is no element that violates the condition. That is a real bug source when the array can legitimately be empty, so validate for emptiness separately. Both also skip holes in a sparse array rather than passing `undefined` to the predicate.
code
javascript · 9 linesconst nums = [1, 3, 5, 8, 9];
let checked = 0;
const hasEven = nums.some(n => { checked++; return n % 2 === 0; });
console.log(hasEven, checked); // true 4 — stopped at 8
console.log([].every(n => n > 100)); // true (vacuously)
console.log([].some(n => n > 100)); // false
console.log(Array(3).some(() => true)); // false — holes are skippedgo deeper
Recall that some answers "is there at least one" and every answers "are they all", both returning a plain boolean, and that the predicate gets the element, its index, and the array.
Explain the short-circuit precisely — some halts on the first truthy result, every on the first falsy one — and state the empty-array results with the vacuous-truth reasoning behind [].every being true.
Demonstrate that you design for the empty case: name a real check, such as a validator or a permission gate, that silently passes on an empty list, and show handling emptiness explicitly before the every call.
Own the fail-closed convention: decide across services that an empty required-set is an error rather than an implicit allow, and make sure that rule is enforced where the data enters rather than at every individual call site.
## Two mirror-image questions `Array.prototype.some(callback, thisArg)` and `Array.prototype.every(callback, thisArg)` are the boolean predicate methods. The callback receives `(element, index, array)` and its **truthiness** decides the outcome — not a strict `true`. - `some` asks "does at least one element satisfy this?" It returns `true` as soon as the predicate returns a truthy value, and `false` only after the whole array has been inspected without one. - `every` asks "do all elements satisfy this?" It returns `false` as soon as the predicate returns a falsy value, and `true` only after the whole array passed. They are De Morgan duals: `arr.some(p)` is equivalent to `!arr.every(x => !p(x))`. Writing the double negative is what you do when only one of them reads naturally for the domain. ## Short-circuiting is observable Because the scan stops early, the predicate call count is observable — which matters if it is expensive, or if the array is large: ```js const nums = [1, 3, 5, 8, 9]; let calls = 0; nums.some(n => { calls++; return n % 2 === 0; }); // true calls; // 4 — stopped at 8, never looked at 9 ``` This is the concrete argument against the common alternative `arr.filter(p).length > 0`: `filter` visits every element, runs the predicate on all of them, and builds an array that is discarded one expression later. For a membership question with an expensive predicate or a long array, `some` does strictly less work and states the intent more clearly. The same applies to `every` versus `filter(p).length === arr.length`. ## The empty-array answers `[].some(anything)` is `false` and `[].every(anything)` is `true`. The predicate is never called in either case. The `every` result is **vacuous truth**: the claim "all elements satisfy P" can only be falsified by exhibiting an element that fails, and an empty array has none, so the claim stands. It is mathematically right and operationally dangerous. A validator such as `fields.every(f => f.valid)` reports "valid" for a form with no fields at all; a permission check such as `requiredRoles.every(r => user.roles.includes(r))` grants access when the required-roles list arrives empty because an upstream call failed. The fix is not to distrust `every`, it is to make emptiness an explicit case: ```js if (fields.length === 0) throw new Error('no fields to validate'); const ok = fields.every(f => f.valid); ``` ## Holes are skipped Unlike the `find` family, `some` and `every` check whether each index actually exists before invoking the predicate, so holes in a sparse array are skipped entirely: ```js Array(3).some(() => true); // false — the predicate never runs Array(3).every(() => false); // true — same reason Array(3).findIndex(x => x === undefined); // 0 — find visits holes ``` So `every` on an all-holes array behaves exactly like `every` on an empty one, which compounds the vacuous-truth trap when the array came from `new Array(n)` or from an assignment that raised `length`. ## Truthiness, not equality The predicate's return value is coerced to a boolean. A predicate that ends with `return item.error` treats the empty string and `0` as "no error" and any non-empty message as "error" — usually what was meant, occasionally not. When the intent is a strict test, write the comparison explicitly (`return item.error != null`) rather than relying on coercion the next reader has to reconstruct. ## Mutation during the scan The index range is fixed by the `length` read when the call starts, so elements appended by the predicate are never visited, and elements changed before their turn are seen with their new value. A predicate with side effects therefore produces results that depend on where the short-circuit lands — a genuinely non-deterministic-feeling bug. Keep predicates pure. ## Picking the right tool Use `some` for "is there any…", `every` for "are they all…", `includes` when you are comparing against a fixed value rather than running a test, and `find`/`findIndex` when you need the matching element or its position rather than a yes/no. Choosing the boolean method when a boolean is what you want keeps both the intent and the work minimal.
- Why prefer `some` over `filter(...).length > 0`?`some` stops at the first match, while `filter` always walks the entire array, runs the predicate on every element, and allocates a result array you immediately discard. On a long array or an expensive predicate that is real wasted work, and the boolean method also states the intent — "is there any" — instead of making the reader infer it from a length comparison.
- How would you express `every` using `some`?They are De Morgan duals: `arr.every(p)` is equivalent to `!arr.some(x => !p(x))`, and `arr.some(p)` to `!arr.every(x => !p(x))`. The equivalence holds for the empty array too — `[].some` is `false`, so its negation is `true`, matching `[].every`. In practice you write whichever direction reads naturally rather than the negated form.
- A permission check `requiredRoles.every(r => user.roles.includes(r))` granted access to everyone after a config change. What happened?`requiredRoles` almost certainly arrived empty, and `every` on an empty array is `true` by vacuous truth, so the check passed for every user. Treat emptiness as its own case: fail closed when the required-roles list is empty or missing, then run the `every` check on a list you have verified is populated.
- Do `some` and `every` visit holes in a sparse array?No. Both test whether each index actually exists before calling the predicate, so holes are skipped. `Array(3).some(() => true)` is `false` because the predicate never runs at all. This differs from `find` and `findIndex`, which read every index and hand a hole to the predicate as `undefined`.
saying these in an interview costs you the question
- Says [].every(p) returns false
- Thinks some keeps scanning after the first match
- Believes the predicate must return exactly true
- Uses filter(...).length > 0 as the membership check
- Expects some and every to visit holes