JavaScript some() answers one narrow question about an array or array-like object: does at least one present element satisfy this test?
Array.prototype.some()returnstrueas soon as its callback produces a truthy result for a present element, and returnsfalseif no element passes the test.
What JavaScript some() Does
some() is an existential test. In plain terms, it checks whether a matching element exists.
The test is supplied as a callback called a predicate. A predicate receives a value and produces a result that JavaScript converts to a boolean.
const scores = [42, 68, 91];
const hasPassingScore = scores.some(score => score >= 70);
console.log(hasPassingScore);
true
The method has this syntax:
array.some(callback, thisArg)
The callback receives three arguments:
array.some((element, index, array) => {
// Return any value.
});
elementis the value at the current index.indexis the current numeric index.arrayis the object being traversed.thisArgis an optional value used asthisinside a regular callback function.
some() converts each callback result to a boolean. The callback does not need to return the literal value true. A nonempty string, object, or nonzero number is truthy and therefore counts as a match.
Once a result is truthy, some() returns true immediately. It does not test the remaining elements. This short-circuiting behavior often appears in JavaScript interview questions because it affects both output and callback counts.
An empty array returns false. There is no present element that can satisfy the predicate.
console.log([].some(value => true));
false
Practical some() Examples
Frontend code often uses some() to detect invalid form fields. The predicate can inspect objects instead of primitive values.
const fields = [
{ name: "email", value: "[email protected]", required: true },
{ name: "company", value: "", required: false },
{ name: "password", value: "", required: true }
];
const hasInvalidRequiredField = fields.some(
field => field.required && field.value.trim() === ""
);
console.log(hasInvalidRequiredField);
true
some() vs every(), find(), findIndex(), includes(), and filter()
Choose the array method from the result the calling code needs. Similar predicates can produce very different outputs.
| Method | Question it answers | Result | Stops early? |
|---|---|---|---|
some(predicate) | Does at least one present element match? | Boolean | Yes, after the first truthy result |
every(predicate) | Do all present elements match? | Boolean | Yes, after the first falsy result |
find(predicate) | What is the first matching value? | Value or undefined | Yes, after the first truthy result |
findIndex(predicate) | Where is the first matching value? | Index or -1 | Yes, after the first truthy result |
includes(value) | Does this value occur in the array? | Boolean | Yes, after finding an equal value |
filter(predicate) | Which values match? | New array | No |
Consider the same product data:
const products = [
{ id: "keyboard", stock: 4 },
{ id: "monitor", stock: 0 },
{ id: "mouse", stock: 8 }
];
console.log(products.some(product => product.stock === 0));
console.log(products.find(product => product.stock === 0));
console.log(products.findIndex(product => product.stock === 0));
console.log(products.filter(product => product.stock === 0));
true
{ id: 'monitor', stock: 0 }
1
[ { id: 'monitor', stock: 0 } ]
Use includes() when equality with a supplied value is the complete test:
const frameworks = ["React", "Vue", "Svelte"];
console.log(frameworks.includes("Vue"));
console.log(frameworks.some(name => name.startsWith("V")));
true
true
The first expression checks equality using the method's value comparison rule. The second applies a custom predicate.
find() and findIndex() also differ from some() on sparse arrays. They invoke their predicates for every index and retrieve an own value, an inherited value, or undefined when no property resolves. some() skips an index only when no property exists there, including on the prototype chain.
These distinctions are useful in worked frontend coding examples because an otherwise correct predicate can still be paired with the wrong result type.
Edge Cases Interviewers Test
Empty arrays are the first boundary case:
console.log([].some(Boolean));
false
Truthy callback results are another common output question. The callback below returns 0 for the first element and 5 for the second. JavaScript converts those values to false and true.
const visited = [];
const result = [0, 5, 9].some(value => {
visited.push(value);
return value;
});
console.log(result);
console.log(visited);
true
[ 0, 5 ]
The value 9 is never visited because the truthy result from 5 ends the search.
A sparse slot is different from an element containing undefined:
const values = [];
values.length = 3;
values[1] = undefined;
values[2] = "ready";
const visitedIndexes = [];
values.some((value, index) => {
visitedIndexes.push(index);
return false;
});
console.log(visitedIndexes);
[ 1, 2 ]
Index 0 is missing, so the callback skips it. Index 1 exists even though its value is undefined.
some() saves the initial traversal length before the first callback call. Appending an element during the search does not extend the range. Existing, unvisited elements are read when their turn arrives.
const numbers = [1, 2, 3];
const seen = [];
numbers.some((value, index, array) => {
seen.push(value);
if (index === 0) {
array.push(4);
array[1] = 20;
delete array[2];
}
return false;
});
console.log(seen);
console.log(numbers);
[ 1, 20 ]
[ 1, 20, <1 empty item>, 4 ]
The appended 4 lies beyond the saved length. The replacement at index 1 is observed. The deleted property at index 2 is absent when that index is checked, so the callback does not run for it.
Mutation during traversal is valid JavaScript, but it is difficult to reason about. Prefer computing the answer without changing the collection unless an interview prompt specifically asks about mutation.
some() is generic, which means it can be called with an array-like object:
const controls = {
0: { invalid: false },
1: { invalid: true },
length: 2
};
const hasInvalidControl = Array.prototype.some.call(
controls,
control => control.invalid
);
console.log(hasInvalidControl);
true
Property existence is checked when each index is reached. The check includes the prototype chain, so an inherited indexed property counts as present.
const prototype = { 1: "inherited" };
const values = Object.create(prototype);
values.length = 3;
const visited = [];
Array.prototype.some.call(values, (value, index) => {
visited.push(`${index}:${value}`);
return false;
});
console.log(visited);
[ '1:inherited' ]
A regular callback can receive thisArg as its this value:
const limits = { maximum: 10 };
const exceedsLimit = [4, 12, 8].some(function (value) {
return value > this.maximum;
}, limits);
console.log(exceedsLimit);
true
An arrow function does not take its this value from thisArg, so use a regular function when the exercise tests this parameter.
If the callback throws an error, some() stops and the error continues to the caller. The method does not convert an exception into false.
Implement some() in an Interview
A typical prompt is:
Implement a function that behaves like
Array.prototype.some()without calling the native method. Return early when a predicate matches.
Start with a runnable stub and tests for the behavior most interviewers expect from ordinary arrays:
function basicSome(array, callback) {
// TODO: implement the traversal and early return.
}
function report(label, passed) {
console.log(label, passed ? "PASS" : "FAIL");
}
report("empty array", basicSome([], Boolean) === false);
report("finds a match", basicSome([1, 4, 8], value => value > 2) === true);
let calls = 0;
basicSome([1, 4, 8], value => {
calls += 1;
return value > 2;
});
report("stops early", calls === 2);
Once those tests fail against the stub, complete the basic solution:
function basicSome(array, callback) {
for (let index = 0; index < array.length; index += 1) {
if (callback(array[index], index, array)) {
return true;
}
}
return false;
}
This version communicates the central algorithm. It checks values from left to right, coerces callback results through the if condition, and returns immediately after a match.
It does not reproduce several behaviors of the native method. It calls the callback for holes, repeatedly reads a changing length, accepts only the assumed array shape, and does not support thisArg.
A stronger interview answer can cover the edge cases without claiming to be a complete production replacement. Define the fidelity tests before revealing the implementation:
function testInterviewSome(implementation) {
const sparse = [];
sparse.length = 2;
sparse[1] = "present";
const visited = [];
implementation(sparse, (value, index) => {
visited.push(index);
return false;
});
console.assert(visited.join() === "1", "skips missing properties");
console.assert(
implementation({ 0: "match", length: Infinity }, Boolean) === true,
"clamps positive Infinity"
);
let bigIntRejected = false;
try {
implementation({ 0: "match", length: 1n }, Boolean);
} catch (error) {
bigIntRejected = error instanceof TypeError;
}
console.assert(bigIntRejected, "rejects a BigInt length");
}
Use the following as the canonical final implementation:
function interviewSome(input, callback, thisArg) {
if (input === null || input === undefined) {
throw new TypeError("interviewSome requires an array-like value");
}
const object = Object(input);
const rawLength = object.length;
if (typeof rawLength === "bigint") {
throw new TypeError("length cannot be a BigInt");
}
const numericLength = Number(rawLength);
const length =
Number.isNaN(numericLength) || numericLength <= 0
? 0
: numericLength === Infinity
? Number.MAX_SAFE_INTEGER
: Math.min(Math.floor(numericLength), Number.MAX_SAFE_INTEGER);
if (typeof callback !== "function") {
throw new TypeError("callback must be a function");
}
for (let index = 0; index < length; index += 1) {
if (index in object) {
const result = callback.call(
thisArg,
object[index],
index,
object
);
if (result) {
return true;
}
}
}
return false;
}
testInterviewSome(interviewSome);
Each part answers a specific interview concern:
- The null check prevents
nullorundefinedfrom being treated as a collection. - The callback check produces a
TypeErrorbefore traversal begins for values whose type is not"function". Object(input)permits array-like input.lengthis calculated once, so later appends do not extend the loop.index in objectskips holes and includes inherited indexed properties.callback.call()suppliesthisArg, the value, the index, and the traversed object.if (result)performs boolean coercion.- The immediate
return truepreserves short-circuiting. - A callback error propagates naturally because the implementation does not catch it.
This implementation is intended for the stated interview exercise. It is not a full standards replacement because JavaScript does not expose the specification's internal IsCallable operation: a class has type "function" but cannot be called, so an empty or all-hole input can return false here where native some() throws a TypeError.
For an input with n indexed positions, the worst case takes linear time because the loop may check all n positions. The function uses constant auxiliary space because it does not allocate storage that grows with the input.
The best way to prepare this answer is to type it into a browser editor, predict each test, and then run it. UIReady Premium Lifetime is relevant when repeated browser exercises, live tests, and framework variants form part of the study plan.
Test Your Implementation and Avoid Common Mistakes
The following test matrix exercises the canonical interviewSome() implementation. It covers the cases that a basic happy-path test misses. Before running it, predict the value of each logged result, why the early-exit callback runs twice, why the sparse array omits index 0, and why "matched" makes the function return true.
const empty = interviewSome([], Boolean);
let earlyCalls = 0;
const early = interviewSome([1, 4, 8], value => {
earlyCalls += 1;
return value > 2;
});
const sparse = [];
sparse.length = 3;
sparse[1] = undefined;
sparse[2] = 7;
const sparseIndexes = [];
interviewSome(sparse, (value, index) => {
sparseIndexes.push(index);
return false;
});
const context = { limit: 5 };
const withThis = interviewSome([2, 7], function (value) {
return value > this.limit;
}, context);
const mutable = [1, 2, 3];
const mutationVisits = [];
interviewSome(mutable, (value, index, array) => {
mutationVisits.push(value);
if (index === 0) {
array.push(99);
array[1] = 20;
delete array[2];
}
return false;
});
const arrayLike = { 0: "skip", 1: "match", length: 2 };
const arrayLikeResult = interviewSome(
arrayLike,
value => value === "match"
);
const truthyResult = interviewSome([0, 2], value =>
value === 2 ? "matched" : ""
);
let callbackError;
try {
interviewSome([1], "not callable");
} catch (error) {
callbackError = error.name;
}
let bigIntLengthError;
try {
interviewSome({ 0: "value", length: 1n }, Boolean);
} catch (error) {
bigIntLengthError = error.name;
}
let classCallbackResult;
try {
classCallbackResult = interviewSome([], class Predicate {});
} catch (error) {
classCallbackResult = error.name;
}
console.log(empty);
console.log(early, earlyCalls);
console.log(sparseIndexes);
console.log(withThis);
console.log(mutationVisits);
console.log(arrayLikeResult);
console.log(truthyResult);
console.log(callbackError);
console.log(bigIntLengthError);
console.log(classCallbackResult);
false
true 2
[ 1, 2 ]
true
[ 1, 20 ]
true
true
TypeError
TypeError
false
The final false demonstrates the disclosed class-constructor difference from native some(). The explanations behind the outputs matter more in an interview than memorizing them.
A frequent implementation mistake is using callback(...) === true. That rejects other truthy results and does not match some().
Another mistake is reading array.length in the loop condition. If the callback appends values, the loop can visit indexes outside the original range.
The async callback trap is more subtle. This example uses the canonical interviewSome() definition above:
async function checkValue(value) {
return value > 10;
}
console.log(interviewSome([1, 2], checkValue));
true
An async function returns a Promise. The Promise object is truthy, so the first present element makes interviewSome() return true immediately. Native some() behaves the same way because it does not await callback results.
When every asynchronous check can run together, await them first and then apply some() to the resolved booleans:
async function hasLargeValue(values) {
const checks = await Promise.all(
values.map(async value => value > 10)
);
return checks.some(Boolean);
}
hasLargeValue([1, 2]).then(result => console.log(result));
false
This separates asynchronous work from the synchronous existence test. For further output-prediction practice, use the interview coding examples and explain each callback call before executing the code.