JavaScript's find returns the first value whose predicate succeeds, or undefined if no predicate call succeeds. Those two routes can produce the same returned value when the matching value itself is undefined. A returned zero, false or empty string can also be a successful match. The useful question is therefore not whether the result looks truthy, but what evidence the operation preserves about the search.
The short answer is to choose the result your next step needs: a value, an index, a Boolean, or an explicit record containing both matchedness and value. Then trace which positions were visited, which value was read, and when the predicate stopped. The original examples below keep those questions separate, including sparse arrays and deliberate mutations. They are small executable teaching cases, not a substitute for defining the actual data contract of an application.
This specialist guide belongs to the Websites root. It also connects to The Gold Standard of Education | Learning That Transfers into Life and the How X Works hub. The worked cases are original teaching examples; their numbers are stipulated so that the reasoning can be checked.
eduKateSG · Websites
Find your next learning step
Distinguish the selected value from evidence that a predicate succeeded. Trace stopping, undefined, sparse reads and mutation before choosing the result contract.
ROUTE 2 · CHAPTERS 4–6
Preserve the evidence
Handle falsy matches, index zero and an explicit one-pass result.
ROUTE 3 · CHAPTERS 7–9
Trace reads over time
Inspect sparse positions, starting length and captured values.
ROUTE 4 · CHAPTERS 10–12
Change the data contract
Separate predicate truthiness, validation and changed catalogue cases.
ROUTE 5 · CHAPTERS 13–14
Test and explain
Choose checks that expose a wrong interpretation and state the consumer contract.
Chapter contents
Define the search result · Chapters 1–3
1. Begin with the product of the search
Preserve the evidence · Chapters 4–6
4. Falsy values are still values
5. Use findIndex when the position is the needed evidence
6. Preserve matchedness and value in one pass when necessary
Trace reads over time · Chapters 7–9
7. Missing positions are visited, with ordinary property reads
8. The starting length fixes the range, not all future values
Change the data contract · Chapters 10–12
10. Predicate truthiness is separate from selected-value truthiness
Test and explain · Chapters 13–14
Imagine a catalogue of scores where zero is a legitimate value. We want the first score at or below zero. The predicate tests that condition, and find returns the selected score. If the first qualifying score is zero, the result is zero. A subsequent if statement that tests the result's truthiness answers a different question from whether the search succeeded.
const scores = [4, 0, -2];
const selected = scores.find(value => value <= 0);
// selected === 0
A learner may expect the later negative two because it looks more obviously below the positive entries. The predicate says at or below zero, however, and the operation stops at the first success in ascending index order. The result depends on both the condition and the sequence. Calling the value best or worst would introduce an ordering objective that the code has not implemented.
Before choosing a method, write the next question in plain language. Do we need the first qualifying value, its position, whether any value qualifies, or every qualifying value? These are related tasks with different outputs. If the next step needs an index for an update, a returned value alone may discard information. If it needs only existence, a value-returning search may invite unnecessary ambiguity.
The practical error is not using find itself. It is letting one return value stand for several meanings without a contract. In a carefully constrained array of non-null objects, undefined may be an adequate no-match signal. In an array whose legitimate matching values include undefined, it is not enough on its own. Define the range of possible values before interpreting the signal, rather than assuming every catalogue has the same shape.
CHAPTER 2 OF 14 · Define the search result
2. Trace the first successful predicate call
Use a visit log to make the operation visible. The callback receives the value, index and array. It can record the first two before returning its condition. For a plain dense array, the log shows ascending positions until a truthy predicate result ends the search. Later positions do not receive predicate calls in that invocation.
const visits = [];
const answer = [8, 3, 5].find((value, index) => {
visits.push([index, value]);
return value < 4;
});
// answer === 3
// visits is [[0, 8], [1, 3]]
Index two is absent from the visit log because index one succeeded. That absence is not evidence that five failed the predicate. The predicate was never called for it. This distinction matters when a search is mistakenly used as a complete validation pass or as a way to perform an action for every entry. Early stopping is part of the product, not an accidental optimisation to ignore.
Change the condition to value below two. All three positions are visited and the result is undefined. The log now supports a different claim: none of these predicate calls succeeded. Change the order to three, eight, five with the original below-four condition, and only index zero is visited. The qualifying value is the same, but the amount of observed work changes with its position.
A useful explanation includes both the result and the stopping point. If a callback sends messages or updates records, the visit sequence affects which effects occur. A search method does not promise to finish those effects for all entries. Keep a diagnostic visit log in a small test when order is the question, and remove assumptions that unvisited entries were checked merely because they were present in the input.
CHAPTER 3 OF 14 · Define the search result
3. Undefined can mean a match or no match
Consider an array containing a genuine undefined value and a predicate that explicitly selects undefined. Find succeeds at that position and returns undefined. Compare an array containing only a number with the same predicate. No call succeeds, and find also returns undefined. The returned values are identical, while the search histories differ.
[undefined, 7].find(value => value === undefined); // undefined
[7].find(value => value === undefined); // undefined
Testing result equals undefined cannot recover the missing distinction in this data contract. Nor can nullish coalescing establish that no match occurred: it supplies a fallback for a nullish result regardless of how that result arose. If undefined is an allowed selected value, a fallback can replace a successful selection. That may be an intended display policy, but it is not evidence about the search's outcome.
Change the data contract to an array of present record objects and use a predicate that selects a record. If every possible successful value is an object, undefined can now distinguish failure for that contract. The method has not changed. The interpretation becomes sound because the permitted successful results exclude the no-match signal. State that assumption, especially when a helper will later be reused with less constrained data.
A practical review asks whether the ambiguity can actually occur in the relevant values. Do not build an elaborate wrapper around a simple constrained case without need. Conversely, do not rely on a constraint that exists only in a comment while runtime inputs can contain other values. The correct representation follows the actual contract. When both routes are possible and the distinction matters, preserve matchedness explicitly or choose an index-returning operation with an appropriate check.
| Input and condition | find value | Match occurred? | findIndex |
|---|---|---|---|
| [undefined, 7], select undefined | undefined | Yes | 0 |
| [7], select undefined | undefined | No | -1 |
| [4, 0, -2], select value <= 0 | 0 | Yes | 1 |
Zero is not the only successful result that fails a truthiness test. False, an empty string, null, undefined and NaN are all falsy values in JavaScript, although a particular predicate may or may not select them. Find returns the selected value rather than a Boolean copy of the predicate's decision. Converting that value to Boolean therefore changes the question.
Imagine feature flags where false is an intentional stored setting. A predicate can select the first Boolean entry, and the selected result can be false. Reporting no setting merely because if selected does not enter its branch would erase a valid explicit choice. Similarly, an empty string can be a legitimate selected label in a system whose contract permits it, rather than a sign that the search failed.
const flags = [false, true];
const chosen = flags.find(value => typeof value === "boolean");
// chosen === false, and the first predicate call succeeded
A changed-context check uses an array of nonempty strings. In that narrower contract, a successful value is always truthy, so a truthiness test might happen to distinguish success. But that fact belongs to the contract, not to find. If the contract expands to allow an empty string, the same test becomes unreliable without any change to the search method's behaviour.
Prefer naming that reveals the distinction. A variable called selectedValue invites a value interpretation; a variable called found can sound Boolean even when it contains a score or object. Names cannot enforce a contract, but they can reduce accidental conversions. For a code review, ask the author to describe what false means at each stage. False returned by the predicate means this position does not qualify; false returned by find can be the value at a qualifying position.
CHAPTER 5 OF 14 · Preserve the evidence
5. Use findIndex when the position is the needed evidence
FindIndex returns the first qualifying index, or minus one if none qualifies. Index zero is a successful position. Its falsiness makes an if-index test particularly misleading, while minus one is truthy despite representing failure. The correct ordinary test is whether the returned index is different from minus one.
const values = [undefined, 7];
const index = values.findIndex(value => value === undefined);
const matched = index !== -1; // true; index is 0
This preserves matchedness even when the qualifying value is undefined. It also gives the position needed for an index-based operation. But reading values[index] later is a separate property read. If the array or its property behaviour changes between the search and that read, the later value may differ from the value observed by the predicate. An index is evidence of where the predicate succeeded during the search, not a permanent snapshot of that position's contents.
For a plain unchanged array with passive data properties, using the successful index to retrieve the value is straightforward. State those assumptions when they matter. If getters, proxies or deliberate mutation are involved, an extra read can have effects or obtain a new value. The solution is not to fear all index-based code, but to avoid silently treating two reads as one observation.
A useful changed-context exercise first searches a stable dense array, then replaces the matching element before retrieving it. The index stays the same while the later value changes. This demonstrates why a helper promising both the original matched value and its position must preserve them at the same observation point. Choose a result representation that matches the promise instead of assuming the array will remain still between separate operations.
CHAPTER 6 OF 14 · Preserve the evidence
6. Preserve matchedness and value in one pass when necessary
If the next step needs both a success flag and the exact value passed to the successful predicate call, an explicit result record can preserve both. For a small plain-array teaching case, start with matched false and value undefined. When the predicate succeeds, save matched true, the current index and the callback's value. The flag carries information that the value alone cannot carry.
function locate(array, test) {
let result = { matched: false, index: -1, value: undefined };
array.find((value, index, source) => {
if (!test(value, index, source)) return false;
result = { matched: true, index, value };
return true;
});
return result;
}
locate([undefined, 7], value => value === undefined);
// { matched: true, index: 0, value: undefined }
This helper deliberately uses find's visit and stopping behaviour. It is not presented as a complete replacement for every built-in edge case or as an immutable snapshot of nested data. Its purpose is to preserve the evidence generated by one search. If test throws, the helper throws; if the selected value is an object, the result stores that object reference rather than a deep copy.
Compare this with running some to establish existence and find to retrieve a value. Two passes may be acceptable for stable data and a pure predicate, but they perform different invocations. A stateful predicate, getter or mutation can make the passes disagree. The second pass does not replay the exact earlier observation automatically. When the contract requires one consistent observation, do the relevant work in one pass.
Avoid adding a success field merely as decoration while still branching on result.value. The consumer must use result.matched for the existence question. Then it can interpret value under the data contract. A clear representation is useful only when its fields retain their meanings through later code. Write a changed-context test where the matching value is undefined to prove that the flag, rather than accidental truthiness, controls the outcome.
CHAPTER 7 OF 14 · Trace reads over time
7. Missing positions are visited, with ordinary property reads
Find visits integer positions in its initial search range even when an array has a hole at a position. In a plain sparse array with no inherited value at that index, reading the position yields undefined. This differs from methods that test property presence and skip absent positions before calling their callback. The visit rule must be checked for the specific method, not borrowed from a familiar array method.
const sparse = [, "ready"];
const seen = [];
sparse.find((value, index) => {
seen.push([index, value]);
return false;
});
// seen is [[0, undefined], [1, "ready"]]
A hole and an own property whose value is undefined can therefore produce the same callback value. If the distinction matters, inspect property presence separately with the correct question: own presence or presence anywhere in the prototype chain. That presence check adds information; it does not change what find's callback value alone means.
Inherited values complicate the simplified phrase that holes are undefined. Ordinary property lookup can find an inherited value at an otherwise absent own index. Use an array-like object with a local prototype to test this without modifying Array.prototype globally. If its prototype supplies index zero, a find call can receive that inherited value. The important mechanism is a property read, not an automatic replacement of every missing own slot by a literal undefined.
A practical transfer test compares a sparse array, a dense array containing undefined, and a local array-like object with an inherited indexed value. Record callback index, callback value and own-property presence separately. The observations answer different questions. This also helps connect the search lesson to the existing own-property guide: a returned value can establish what lookup produced without proving that the container stored that value as its own property.
CHAPTER 8 OF 14 · Trace reads over time
8. The starting length fixes the range, not all future values
For the ordinary search, the array's length is obtained before callback iteration proceeds. That starting extent determines the positions considered. It does not copy every value in those positions into a stable snapshot. Later property reads can observe changes made during an earlier callback. Range selection and value observation occur at different times.
const data = [1, 2];
const visited = [];
data.find((value, index) => {
visited.push([index, value]);
if (index === 0) data.push(3);
return false;
});
// visited is [[0, 1], [1, 2]]; the appended index 2 is outside the range
Now change data[1] to nine during the callback at index zero instead of appending. The later callback at index one receives nine, because that position remains inside the initial range and its value is read later. These two mutations have different effects. Saying that find ignores changes is false; saying that it visits every newly appended value is also false.
Deletion gives a third case. Delete index one during the first callback of a plain array with no inherited value there. The later visit still occurs, but its ordinary read yields undefined. If the predicate selects undefined, that visit can succeed. Deletion did not necessarily remove the position from the search range. The particular read result depends on the resulting property environment.
These examples are diagnostic tools, not encouragement to mutate a searched collection casually. In application code, avoid mutation when a stable search is the intended contract, or document its role explicitly. When analysing an existing bug, however, do not simplify away mutation that actually occurs. Write a timeline showing initial length, each property read, each predicate result and any intervening change. That timeline explains the behaviour more accurately than a before-and-after array printout alone.
CHAPTER 9 OF 14 · Trace reads over time
9. Find returns the value read before the predicate ran
The value supplied to a predicate is read before that predicate invocation. If the predicate replaces the current array element and then succeeds, find returns the earlier value passed to the predicate, not a fresh read of the current position after the callback. This distinction is especially useful when a search appears to return a value that is no longer in the array's final snapshot.
const items = ["before"];
const result = items.find((value, index, source) => {
source[index] = "after";
return true;
});
// result === "before"; items[0] === "after"
There is no contradiction. The read happened first, producing before. The callback then changed the property and returned true. The successful result preserved the read value. Logging only items after the call would show after and conceal the value on which the predicate operated. The evidence needed to explain the result includes the sequence, not just the final container.
Compare findIndex followed by a separate items[index] read in the same changed example. The index identifies zero, but the later read obtains after. That can be exactly what an application wants if it needs the current position's value. It is different from promising the value observed during the match. Give the two products different names when both are used.
If the value is an object, preserving the value does not freeze the object's properties. A predicate can mutate the object and find can return the same object reference, now showing changed contents. Replacing an array property with a new object and mutating the original object are different changes. A precise trace records identity as well as fields when that distinction matters. The returned reference preserves which object was selected, not a historical deep copy of its state.
A getter-based teaching case can expose the extra-read issue particularly clearly. Create a local array-like object with length one and a getter at index zero. Let the getter increment a counter and return that count. A find predicate that always succeeds receives one, and find returns one after one getter call. A findIndex search also succeeds at zero, but a subsequent property read invokes the getter again and can return two. These are deliberately active properties. The example does not imply that ordinary stored numbers change by themselves; it shows why a helper's promised observation must match the operations it performs.
Keep that example local. There is no reason to install an indexed getter on a shared global prototype merely to demonstrate the rule. A small object with its own getter and a length property lets Array.prototype.find.call perform the search without affecting unrelated arrays. Reset the object and counter for each comparison so that one experiment's reads do not leak into the next. Otherwise, the sequence starts at a different count and the expected outputs become hard to interpret.
CHAPTER 10 OF 14 · Change the data contract
10. Predicate truthiness is separate from selected-value truthiness
Find interprets the predicate's return through Boolean conversion. A predicate need not return the literal true to succeed. A truthy object can end the search even if the selected array value is falsy. Conversely, a false predicate result rejects a truthy array value. These are two independent values with different roles in the operation.
Suppose the array contains zero followed by five, and the predicate always returns an empty object. The first callback succeeds because the returned object is truthy, so find returns zero. The result is falsy even though the predicate's result was truthy. This controlled case makes it impossible to confuse the decision value with the selected value if the trace labels both.
An async callback introduces a related trap. Calling an async function returns a promise object; find does not await that promise before deciding whether the callback result is truthy. A promise that will eventually fulfil with false is still an object at the decision point. The existing some-and-every guide develops asynchronous predicate limits in detail. Here, the essential boundary is that this synchronous search cannot infer a later Boolean result from the promise's eventual settlement.
For asynchronous selection, design an explicit process with the required ordering, awaiting and failure behaviour rather than inserting async into a synchronous predicate and expecting new semantics. The exact design depends on whether work may run concurrently and whether the first qualifying result means first in input order or first to finish. Those are distinct reader jobs. A clear find explanation stops at identifying the mismatch and routes the learner to the appropriate asynchronous design question.
CHAPTER 11 OF 14 · Change the data contract
11. A selected object is not a validation certificate
A predicate can check one property and return a record that lacks other properties required by a later operation. Find reports that the supplied predicate succeeded; it does not validate every field, establish trust in an external input or clone the record into a safe form. The meaning of a match is only as strong as the condition that produced it.
Imagine records with id and amount fields. A predicate selects the first record whose id equals wanted. If amount is absent or malformed, the record can still be selected because the predicate did not test amount. A later calculation must rely on a suitable data contract or perform the needed checks. Calling the variable verifiedRecord would overstate what the code established.
A selected object also remains shared with its source unless a separate copying step changes that relationship. Mutating a field through the returned reference can affect the object observed through the original array. This is normal reference behaviour, not find mutating the source by itself. Distinguish the search operation from later consumer actions and from effects performed inside the predicate.
A useful evidence record can therefore include the predicate's purpose in words: matched by id, not yet checked for numeric amount. That wording is valuable in code comments, tests and user-facing explanations of a data pipeline. It helps the next step request the right evidence instead of treating selection as an all-purpose approval. When a complete validation pass is needed, use a process designed to visit and assess the required inputs rather than borrowing the confidence suggested by a successful search.
The callback's receiver is another input worth making explicit when a predicate reads this. Find accepts a thisArg for an ordinary callback. An ordinary strict predicate can therefore read a threshold from the supplied object while receiving each candidate value separately. That threshold object is not the selected array value, and it is not automatically the array. Name the two roles clearly: candidate value and comparison settings. A test that accidentally closes over a global threshold may pass while failing to exercise the supplied receiver at all.
An arrow predicate retains its lexical this, so supplying thisArg does not give its body a new dynamic receiver. A simple alternative is to close over a clearly named settings variable deliberately. The important point is consistency between the chosen predicate form and the explanation. Do not add thisArg as if it were a parameter the callback receives after value, index and source; it controls an ordinary call's receiver instead. If the threshold object changes during the search, later calls can observe the changed property, which returns us to the timing question rather than a special selection rule.
CHAPTER 12 OF 14 · Change the data contract
12. Build a changed-context catalogue exercise
Start with an invented catalogue of values four, zero and minus two. Select the first value at or below zero. Record value zero, matched true, index one and visits zero then one. Then change only the order to minus two, four, zero. The first matching value becomes minus two at index zero. The predicate is unchanged; the ordering of candidates changed the result.
For the next card, use undefined followed by seven and select undefined. Ask for both the value and matchedness. A value-only answer of undefined is incomplete if the task requires distinguishing success from failure. Change the input to seven alone. The value remains undefined, but matchedness becomes false. This is the central transfer check: a different search history can share the same returned value.
A third card keeps the successful index but changes the element afterward. Ask separately for the value observed during the search and the value currently stored at that position. A fourth card uses an object and mutates a field through the selected reference. Ask whether identity changed, whether contents changed and whether the array property was replaced. Each card isolates a distinct part of the data story.
Finish by removing an assumption. Replace passive data properties with a getter that returns a different value on each read. A second retrieval may now differ without an explicit assignment between the two reads. The correct response is to trace the reads, not to insist that the index guarantees a snapshot. This exercise scales from a simple catalogue to more complex application data because it teaches the learner to name the evidence preserved by each operation.
Here is a full hand trace for a further invented case. Start with an array of length three containing two, undefined and four. The predicate selects undefined. At index zero, the read produces two, so the predicate fails. At index one, the read produces undefined, so the predicate succeeds and the operation stops. The returned value is undefined, the successful index would be one, and index two was not tested. A value-only log loses the difference between this trace and an unsuccessful search, while the explicit visit ledger preserves it.
Now alter only the first callback so that it replaces index one with six before returning false. The second read produces six, so that call fails; index two produces four and fails as well. The final value is again undefined, but now no predicate call succeeded. This pair of traces demonstrates both ambiguity and live reads within the original range. The same final result does not establish the same path, and the same initial array does not establish the same observed sequence when the callback changes future positions.
Finally, leave the first callback unchanged but append an undefined value beyond the original three positions. That new position is outside the starting range and is not tested by this invocation. If the application needs to search a collection that grows during processing, it must define that behaviour explicitly. Repeatedly starting a new search can also repeat effects, so a changed requirement needs a deliberate process rather than an assumption that a built-in synchronous search keeps expanding its work.
CHAPTER 13 OF 14 · Test and explain
13. Choose checks that expose the wrong interpretation
A test suite containing only nonempty object matches may never expose an incorrect truthiness check. Include a successful zero or false when those values are allowed. Include a successful undefined and a no-match undefined when the contract permits the ambiguity. Include a successful index zero and failure index minus one to detect an inverted findIndex condition. These cases test consumer interpretation, not merely the built-in method.
For visit behaviour, use a small callback log with an expected stopping point. For sparse behaviour, record both value and own presence. For mutation, inspect the observed callback value and final array separately. Each check should have a purpose that can be stated before execution. A large input with many repeated ordinary values can look thorough while leaving the relevant distinction untested.
Do not claim that find itself guarantees a side-effect-free search. A predicate can change external state, a getter can run code, and a thrown error can stop the operation. If the callback updates a counter before throwing, the earlier update is not rolled back by the search. A caught exception therefore does not establish that nothing happened. Keep failure effects visible when the application relies on them.
An appropriate practical check uses a fresh local collection and a small controlled predicate. Write the expected value, matchedness, index and visit list where relevant, then compare the actual results. If a failure appears, classify it as an incorrect condition, wrong output representation, misunderstood visit rule or unaccounted mutation. That classification suggests the next repair more directly than rewriting the entire search expression until a familiar example happens to pass.
An empty array provides a useful boundary check: no predicate call occurs, and find returns undefined. A callback counter should remain zero. This separates failure after testing candidates from absence of candidates altogether. The returned value alone does not preserve that distinction either, so include a visit count when the practical question concerns whether any comparison was actually performed.
CHAPTER 14 OF 14 · Test and explain
14. Finish with a result contract the next step can trust
A complete short explanation can say that find visited positions in ascending order, read a value, called the predicate with it and stopped at the first truthy predicate result. It returned that observed value. If no call succeeded, it returned undefined. Whether undefined proves failure depends on whether undefined was also an allowed successful value. That final qualification connects language behaviour to the actual data contract.
For a consumer needing only existence, choose an existence result with an understood visit rule. For a consumer needing a position, use an index result and compare it with minus one. For a consumer needing both the original selected value and success evidence under a broad value contract, preserve an explicit record in one pass. These choices follow the reader's job, rather than treating one method as the preferred answer to every search task.
As independent practice, write three predictions before running code: a successful falsy value, a successful undefined value and a failed search. Then add a mutation of the successful position during the predicate. Explain why the returned value and final array can differ. Keep the visit log small enough that each entry can be accounted for. The goal is a defensible trace, not a memorised output string.
The lasting habit is to distinguish a result from the evidence it carries. A selected value, a successful index, a Boolean and a snapshot are different products. Find provides one of them with a defined visit sequence and stopping rule. Once those boundaries are clear, undefined becomes an interpretable value rather than a mystery, and a short search expression becomes something a learner can explain, test and use with the right degree of confidence.
Continue through the verified reading route
Predicate scope: some and every versus complete validation
Predicate scope: some and every versus complete validation. Use this for early stopping, complete checks, sparse-array differences and asynchronous predicate boundaries.
Presence evidence: own properties and inherited lookup
Presence evidence: own properties and inherited lookup. Use this when a callback value must be distinguished from an own slot or a value supplied by the prototype chain.
Read timing: Array with replacement and skipped reads
Read timing: Array with replacement and skipped reads. Use this for a different array operation where the exact read sequence affects getters and observed values.
Frequently asked questions
Does undefined always mean find found nothing?
No. It can also be the value at a position whose predicate succeeded. The data contract determines whether that ambiguity is possible.
Can zero or false be a successful result?
Yes. Find returns the selected value, not the Boolean result of its predicate. A truthiness test of the selected value can therefore misclassify a match.
Is if index correct after findIndex?
No. Zero is a valid successful index and minus one signals failure. For ordinary findIndex results, compare the index with minus one explicitly.
Does find skip holes like some other array methods?
No. It visits positions in its initial range and reads their values. A plain absent position yields undefined, while inherited indexed properties can affect ordinary lookup.
Does find reread the matching position after the predicate changes it?
No. It returns the value read and passed into the successful predicate call. A later separate property read can obtain a different value.
Does an async predicate make find await its decision?
No. A promise object is truthy at the synchronous decision point. Design an explicit asynchronous selection process with the ordering and failure behaviour the task requires.
Authoritative sources and further reading
ECMAScript: Array.prototype.find. Normative value result and the shared predicate-search operation.
ECMAScript: Array.prototype.findIndex. Normative index result, including minus one for no success.
MDN: Array.prototype.find. Reference behaviour for early stopping, sparse positions and mutation examples.
Return to the Websites subject guide, The Gold Standard of Education, or the How X Works hub.