<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Devin</title>
    <description>The latest articles on DEV Community by Devin (@devindev).</description>
    <link>https://dev.to/devindev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4192015%2F38a071c7-3ce6-4ddd-839c-3ebd68567d7c.png</url>
      <title>DEV Community: Devin</title>
      <link>https://dev.to/devindev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devindev"/>
    <language>en</language>
    <item>
      <title>Écrire un article complet sur comment genere un revenu passif avec l'ia sans inv</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 16:42:51 +0000</pubDate>
      <link>https://dev.to/devindev/ecrire-un-article-complet-sur-comment-genere-un-revenu-passif-avec-lia-sans-inv-48m1</link>
      <guid>https://dev.to/devindev/ecrire-un-article-complet-sur-comment-genere-un-revenu-passif-avec-lia-sans-inv-48m1</guid>
      <description>&lt;h1&gt;
  
  
  Automating Content Workflows with the OpenAI API and Node.js
&lt;/h1&gt;

&lt;p&gt;Producing useful content repeatedly is a workflow problem, not just a writing problem. A business may have approved product details, webinar transcripts, or internal notes that need to become consistent articles, newsletter sections, or social posts. A small Node.js program can send a focused brief to the OpenAI API, receive a first draft, apply basic validation, and save it for an editor. That removes repetitive setup work while preserving human responsibility for accuracy, voice, and publication.&lt;/p&gt;

&lt;p&gt;This tutorial builds a command-line draft generator using Node.js 18 or later and its built-in &lt;code&gt;fetch&lt;/code&gt; API. It requires no third-party packages. The example accepts a topic, requests a Markdown article through the OpenAI Responses API, checks that the response is complete and plausible, and then writes a new file under &lt;code&gt;articles/&lt;/code&gt;. It intentionally does not publish content automatically.&lt;/p&gt;

&lt;p&gt;The complete standalone script is available at &lt;a href="//../code/content-automation-openai-nodejs.js"&gt;&lt;code&gt;code/content-automation-openai-nodejs.js&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide what to automate
&lt;/h2&gt;

&lt;p&gt;Begin with a repeatable content task and a clear boundary. For example, a small company might want to turn an approved webinar transcript into an article draft and a few social snippets. Define the input material, the expected outputs, and the checks an editor will perform. A vague instruction such as “make content” is hard to evaluate; a brief that names the audience, format, length, and source constraints is much more useful.&lt;/p&gt;

&lt;p&gt;Treat generated content as a draft. Language models can produce fluent but unsupported claims, omit important context, or misrepresent source material. They do not independently verify facts just because a prompt asks them to. An editor should compare important claims with approved source material, check technical examples, and approve every piece before it is published.&lt;/p&gt;

&lt;p&gt;For a first implementation, automate one narrow step: create one draft from one topic. Avoid starting with a publishing integration, a complex queue, or a multi-stage autonomous agent. Keeping the first version small makes failures easier to identify and the generated result easier to review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Node.js and API access
&lt;/h2&gt;

&lt;p&gt;Install a current Node.js version that supports global &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;AbortSignal.timeout&lt;/code&gt; (Node.js 18 or later). Create an API key in your OpenAI account and pass it to the process as &lt;code&gt;OPENAI_API_KEY&lt;/code&gt;. Never put a real key in source code, a browser application, or a committed config file. In production, store it in your hosting platform’s secret manager and restrict which services and people can access it.&lt;/p&gt;

&lt;p&gt;For the current PowerShell session, set the environment variable with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_api_key"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script optionally reads &lt;code&gt;OPENAI_MODEL&lt;/code&gt;; otherwise it uses &lt;code&gt;gpt-4.1-mini&lt;/code&gt;. Model availability, capabilities, and pricing can change, so choose a model available to your account and confirm its current details before deploying a workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send a focused request
&lt;/h2&gt;

&lt;p&gt;The generator posts JSON to &lt;code&gt;https://api.openai.com/v1/responses&lt;/code&gt;. It places stable editorial requirements in &lt;code&gt;instructions&lt;/code&gt; and the topic-specific task in &lt;code&gt;input&lt;/code&gt;. Separating these makes it easier to adjust the article brief without mixing it into command-line parsing. The request also sets a finite output-token limit and a timeout. Neither of those guarantees a precise word count, so the prompt and later validation handle length separately.&lt;/p&gt;

&lt;p&gt;The essential request shape is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.openai.com/v1/responses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Write a careful technical blog article in English.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Draft a Markdown article about the supplied topic...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_output_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full script checks the HTTP status before interpreting the body. If the API returns an error, it reports the status and a limited excerpt of the response instead of pretending that generation succeeded. It separately handles network failures, timeouts, invalid JSON, incomplete responses, and responses without text. These explicit checks matter: a failed request should not produce an apparently successful empty or partial article.&lt;/p&gt;

&lt;p&gt;The topic is user input, so constrain its length and treat it as data. Prompt wording can establish the task, but it is not a security boundary: do not trust generated text as instructions to execute, as HTML to render without escaping, or as verified source material.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract and validate the draft
&lt;/h2&gt;

&lt;p&gt;Responses can include multiple output items and content blocks. The example walks the returned items and collects blocks whose type is &lt;code&gt;output_text&lt;/code&gt;, rather than assuming the article always occupies a fixed position in an array. It rejects an empty result and checks that the draft begins with a Markdown heading and falls within a broad word-count range.&lt;/p&gt;

&lt;p&gt;These are structural checks, not a quality guarantee. A title and ~1,000 words do not prove that the article is original, technically correct, appropriate for the audience, or supported by evidence. Automated validation should catch clear format failures; editorial review should assess meaning. If a particular workflow requires claims to come only from a transcript or product specification, compare those claims against that approved source instead of relying on a general-purpose word-count check.&lt;/p&gt;

&lt;p&gt;For a workflow with several deliverables, validate each output independently. Check that required fields exist, each text section is non-empty, and content stays within practical length limits. If a later stage consumes structured data, use a documented format and validate it against a schema before passing it on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Save drafts without overwriting work
&lt;/h2&gt;

&lt;p&gt;The script creates a filename slug from the topic, resolves the output beneath the project’s &lt;code&gt;articles/&lt;/code&gt; directory, and writes UTF-8 Markdown. It uses the filesystem’s exclusive &lt;code&gt;wx&lt;/code&gt; flag, which fails if the destination already exists. That small safeguard prevents a repeated run from silently replacing an earlier draft.&lt;/p&gt;

&lt;p&gt;Run the command from the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node code/content-automation-openai-nodejs.js "Reliable JavaScript API clients"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a file such as &lt;code&gt;articles/reliable-javascript-api-clients.md&lt;/code&gt;. If that path already exists, the script reports an error; choose another topic or move the previous draft deliberately. The script creates the &lt;code&gt;articles/&lt;/code&gt; directory if necessary and prints the saved path only after the write succeeds.&lt;/p&gt;

&lt;p&gt;The filename is derived from a constrained slug rather than using the raw topic as a path. This keeps the output predictable and avoids allowing path separators or punctuation in a user-provided topic to choose arbitrary destinations. In a multi-user service, define an output ownership model and enforce authorization before accepting generation requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add safeguards before scaling
&lt;/h2&gt;

&lt;p&gt;Each successful request may incur usage charges. Set a spending budget and usage alerts, impose input and output limits, and restrict who can trigger generation. Monitor request volume and cost per deliverable. Avoid logging API keys, and review whether prompts or source files contain customer information before sending them to an external service. Follow the provider’s terms and your organization’s data-handling requirements.&lt;/p&gt;

&lt;p&gt;The example uses a timeout but does not retry. A production service may retry transient network failures or rate limits, but retries should be bounded, delayed with backoff, and limited to errors that may recover. Repeating a request with invalid credentials or an unsupported model will not solve the problem and may increase cost. At higher volume, add concurrency limits and a job queue so bursts do not overwhelm the service or exceed account limits.&lt;/p&gt;

&lt;p&gt;Keep generation separate from publication. Save drafts in a review queue, make the approval step explicit, and ensure that retries or duplicate triggers cannot accidentally publish multiple copies. Before approving a draft, check facts against sources, run any code examples, inspect links and formatting, and confirm that the content respects permissions and brand standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation: generate social media drafts
&lt;/h2&gt;

&lt;p&gt;The same workflow can produce platform-specific social copy from a topic or an editor-approved article. Instead of publishing automatically, generate a small set of drafts that a person can edit and approve. This keeps the repetitive work—adapting a message to different formats—automated while protecting the brand from unsupported claims, awkward tone, and accidental posts.&lt;/p&gt;

&lt;p&gt;The standalone example at &lt;a href="//../code/social-media-content-generator.js"&gt;&lt;code&gt;code/social-media-content-generator.js&lt;/code&gt;&lt;/a&gt; uses Node.js 18 or later and the OpenAI Responses API. Pass a short brief as a command-line argument, and it requests distinct drafts for LinkedIn, X, and Instagram. The program asks for JSON, checks that all three drafts are present, enforces a 280-character limit for the X text, and prints the result as Markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node code/social-media-content-generator.js "Share practical ways small teams can use AI to summarize meeting notes"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; in the environment before running, and optionally set &lt;code&gt;OPENAI_MODEL&lt;/code&gt; to a model enabled for your account. The script does not require an SDK or other package. Its length check is a simple guard, not a guarantee of platform acceptance: character counting rules and publishing requirements can change, so verify them against each platform before use.&lt;/p&gt;

&lt;p&gt;For better results, provide approved source material rather than relying on a broad topic alone. A production workflow could accept a reviewed article, product facts, intended audience, and call to action, then pass only the necessary information to the API. Keep platform-specific constraints explicit and validate the generated response before presenting it to an editor. Never include confidential customer information unless its use is authorized.&lt;/p&gt;

&lt;p&gt;Generation should remain separate from scheduling and publishing. Review every draft for factual accuracy, tone, links, and current platform rules; then use the platform's authorized publishing tools only after approval. This simple approval boundary makes automation useful without treating generated copy as ready-to-post content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extend the workflow deliberately
&lt;/h2&gt;

&lt;p&gt;After the first version is useful, improve it in response to real editing friction. A structured brief could include audience, tone, source material, and required sections. Validate each field before making a request. You might then add a second step that derives social posts from an editor-approved article, or notify an editor when a draft is ready. Each additional stage should have a defined input, output, failure mode, and review point.&lt;/p&gt;

&lt;p&gt;The practical advantage of the OpenAI API and Node.js is that a modest program can connect a repeatable task to a capable text-generation service without a large framework. But dependable content automation comes from the surrounding workflow: relevant inputs, explicit limits, measurable checks, careful handling of data, and accountable editorial review. Automate the first draft; keep a person responsible for what readers ultimately see.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>openai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Écrire un article complet sur les algorhytme en JavaScriptavec exemples de code, explications claires et cas d'usage réels. - 1792340690132</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 16:24:52 +0000</pubDate>
      <link>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-2bd</link>
      <guid>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-2bd</guid>
      <description>&lt;h1&gt;
  
  
  Bubble Sort and Quick Sort in JavaScript
&lt;/h1&gt;

&lt;p&gt;Algorithms are the step-by-step methods behind everyday JavaScript tasks, from searching arrays to sorting data for a user interface. Choosing an appropriate algorithm matters because the amount of work can grow quickly as data sets get larger, affecting application speed and responsiveness. Comparing Bubble Sort and Quick Sort offers a practical way to see how different strategies solve the same problem—and why their performance can differ so dramatically.&lt;/p&gt;

&lt;p&gt;Big O notation describes how an algorithm's resource requirements grow with input size, commonly written as &lt;code&gt;n&lt;/code&gt;. It is not a promise of an exact runtime; instead, it highlights the dominant growth pattern. For example, an O(n) algorithm generally does work proportional to the number of items, while an O(n²) algorithm can require roughly four times as much work when the input doubles. Understanding these complexity classes helps developers reason about scalability and choose implementations that remain practical as their applications grow.&lt;/p&gt;

&lt;p&gt;The examples below sort arrays of numbers in ascending order and return a new array, leaving the input unchanged. They work with empty arrays, duplicates, and negative values. The complete, dependency-free JavaScript example is also available in &lt;code&gt;code/bubble-sort-vs-quicksort.js&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bubble Sort: compare neighbors
&lt;/h2&gt;

&lt;p&gt;Bubble Sort repeatedly scans an array and compares adjacent values. If the left value is greater than the right value, it swaps them. At the end of each pass, the largest value in the still-unsorted section has moved to its final position. The next pass can stop one element earlier.&lt;/p&gt;

&lt;p&gt;For example, start with &lt;code&gt;[5, 1, 4, 2, 8]&lt;/code&gt;. Comparing &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; causes a swap, giving &lt;code&gt;[1, 5, 4, 2, 8]&lt;/code&gt;. The next comparison swaps &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt;, then &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt;. At the end of that pass, &lt;code&gt;5&lt;/code&gt; is in its final place, just before &lt;code&gt;8&lt;/code&gt;. More passes sort the remaining prefix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;swapped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;swapped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;swapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2, 4, 5, 8]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [5, 1, 4, 2, 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;end&lt;/code&gt; index marks the last value that still needs to be considered. The inner loop stops there because every value beyond it has already been placed by an earlier pass. The &lt;code&gt;swapped&lt;/code&gt; flag records whether the pass changed the array. If it did not, every adjacent pair was already in order, so the algorithm can stop without doing redundant passes.&lt;/p&gt;

&lt;p&gt;That early exit gives Bubble Sort a best-case time complexity of &lt;strong&gt;O(n)&lt;/strong&gt; when the input is already sorted: it makes one pass and finds no swaps. On average and in the worst case, it takes &lt;strong&gt;O(n²)&lt;/strong&gt; time. A reverse-sorted array is especially demanding because many pairs must be swapped over many passes. Doubling the input size can therefore require roughly four times the work.&lt;/p&gt;

&lt;p&gt;Bubble Sort is stable when implemented with the strict &lt;code&gt;&amp;gt;&lt;/code&gt; comparison shown here. Equal values are not swapped, so their relative order is retained. Its in-place sorting process needs &lt;strong&gt;O(1)&lt;/strong&gt; working space, but this function copies its input first, so the returned-result version requires &lt;strong&gt;O(n)&lt;/strong&gt; additional memory. Keeping the input unchanged is often a useful API choice, but it must be included in the space analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Sort: partition, then recurse
&lt;/h2&gt;

&lt;p&gt;Quick Sort uses a divide-and-conquer strategy. It selects a pivot, partitions the current section into values below, equal to, and above the pivot, then sorts the lower and upper sections recursively. Once a section has fewer than two values, it is already sorted and recursion stops.&lt;/p&gt;

&lt;p&gt;The implementation below uses the middle-position element as its pivot and a three-way partition. It groups all values equal to the pivot together, which is helpful for input containing many duplicates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sortRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;less&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;greater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;less&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;less&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
        &lt;span class="nx"&gt;less&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;greater&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;greater&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
        &lt;span class="nx"&gt;greater&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;sortRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;less&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;sortRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greater&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;sortRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [-1, 3, 3, 7, 8, 9]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [9, 3, 7, 3, -1, 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three indexes define the partition as it is built. Values before &lt;code&gt;less&lt;/code&gt; are below the pivot. Values from &lt;code&gt;less&lt;/code&gt; up to, but not including, &lt;code&gt;current&lt;/code&gt; are equal to it. Values after &lt;code&gt;greater&lt;/code&gt; are above it. Between &lt;code&gt;current&lt;/code&gt; and &lt;code&gt;greater&lt;/code&gt; are values that have not yet been classified.&lt;/p&gt;

&lt;p&gt;When the current value is less than the pivot, it is moved into the lower region and both &lt;code&gt;less&lt;/code&gt; and &lt;code&gt;current&lt;/code&gt; advance. If it is greater, it is exchanged with the value at &lt;code&gt;greater&lt;/code&gt;, and &lt;code&gt;greater&lt;/code&gt; moves left. In that case &lt;code&gt;current&lt;/code&gt; does not advance: the value moved into its position has not been examined yet. Equal values simply advance &lt;code&gt;current&lt;/code&gt;. When the partition loop ends, the equal region is in place, so recursion is needed only for the lower and upper regions.&lt;/p&gt;

&lt;p&gt;The base condition &lt;code&gt;low &amp;gt;= high&lt;/code&gt; handles ranges of zero or one item, including the initial call for an empty array. It also guarantees that recursive calls eventually stop. Because the function sorts a copy, its returned array is independent of the original.&lt;/p&gt;

&lt;p&gt;With reasonably balanced partitions, Quick Sort runs in &lt;strong&gt;O(n log n)&lt;/strong&gt; average time. Each partition examines the values in its section, and balanced recursion creates approximately &lt;code&gt;log₂(n)&lt;/code&gt; levels. However, its worst-case time is &lt;strong&gt;O(n²)&lt;/strong&gt; if each pivot produces highly uneven partitions—for example, one empty side and one side containing nearly every other value. Choosing the item at the middle index is straightforward, but does not ensure that the pivot's value is near the median.&lt;/p&gt;

&lt;p&gt;Partitioning itself uses &lt;strong&gt;O(1)&lt;/strong&gt; additional space, but recursive calls consume stack space: about &lt;strong&gt;O(log n)&lt;/strong&gt; for balanced partitions and up to &lt;strong&gt;O(n)&lt;/strong&gt; in the worst case. This implementation also copies the input, adding &lt;strong&gt;O(n)&lt;/strong&gt; memory. Quick Sort is generally not stable; partition swaps may change the relative order of values that compare equally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing the trade-offs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Best time&lt;/th&gt;
&lt;th&gt;Average time&lt;/th&gt;
&lt;th&gt;Worst time&lt;/th&gt;
&lt;th&gt;Stable?&lt;/th&gt;
&lt;th&gt;Extra space in these examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bubble Sort&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n²)&lt;/td&gt;
&lt;td&gt;O(n²)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;O(n) for the copied result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quick Sort&lt;/td&gt;
&lt;td&gt;O(n log n)&lt;/td&gt;
&lt;td&gt;O(n log n)&lt;/td&gt;
&lt;td&gt;O(n²)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;O(n) copy plus recursion stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Big O describes how resource use grows as the input gets larger; it does not predict exact elapsed time for every array. The values' distribution, the JavaScript engine, and allocation costs also affect measured performance. The three-way Quick Sort partition is particularly useful when many elements are equal: it places the entire equal group in one pass instead of sorting those values repeatedly.&lt;/p&gt;

&lt;p&gt;Bubble Sort's small amount of code makes it a good teaching tool for nested loops, comparisons, swaps, and loop bounds. It is rarely appropriate for a large production collection because its quadratic growth becomes costly quickly. Quick Sort is usually much faster on average for larger inputs, but the pivot strategy and recursion depth matter. Its simpler recursive implementation is best understood as an algorithm example, not a universal guarantee of fast or safe sorting.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use each algorithm
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose Bubble Sort for learning or tiny, nearly sorted collections—not as a general-purpose production sort.&lt;/strong&gt; Its implementation is easy to follow when teaching comparison-based sorting, loop invariants, or why quadratic algorithms scale poorly. The early-exit optimization can also make it reasonable for a very small collection that is already sorted or needs only a few local adjustments. Even then, the benefit is narrow: for typical application data, JavaScript's built-in sort is clearer and more thoroughly optimized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Quick Sort when you need to understand or implement an in-memory general-purpose sort and average-case speed matters.&lt;/strong&gt; Its average O(n log n) running time makes it a much better fit than Bubble Sort as input sizes grow, and a three-way partition can handle collections with many duplicate values efficiently. It can be useful in algorithm exercises or environments where the sorting strategy must be explicit. The implementation still needs a thoughtful pivot strategy, however; poor partitions can lead to O(n²) work and deep recursion.&lt;/p&gt;

&lt;p&gt;For application code, these are usually educational trade-offs rather than a decision to write either algorithm yourself. Prefer JavaScript's built-in &lt;code&gt;sort()&lt;/code&gt; with an appropriate comparator: it avoids maintaining a custom implementation and lets the JavaScript engine choose its sorting strategy. If stability, predictable worst-case performance, or memory limits are requirements, check the guarantees of the specific runtime or choose an algorithm designed to meet them instead of assuming Quick Sort provides them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big O notation: a simple guide to algorithmic complexity
&lt;/h2&gt;

&lt;p&gt;Big O notation describes how an algorithm's time or extra memory grows as its input size grows. It does not predict an exact runtime in milliseconds; instead, it helps compare how approaches scale. The input size is usually written as &lt;code&gt;n&lt;/code&gt;, and Big O focuses on the dominant growth rate rather than constant factors.&lt;/p&gt;

&lt;p&gt;An operation that does not depend on the input length is &lt;strong&gt;O(1)&lt;/strong&gt;, or constant time. Reading an array element by index is one example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getFirst&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt; &lt;span class="c1"&gt;// "red"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A loop that visits each item once is &lt;strong&gt;O(n)&lt;/strong&gt;, or linear time. If the array doubles in size, the number of visits roughly doubles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt; &lt;span class="c1"&gt;// 12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two loops that examine every pair typically produce &lt;strong&gt;O(n²)&lt;/strong&gt;, or quadratic time. Doubling the input can make the work roughly four times larger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;countPairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;countPairs&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt; &lt;span class="c1"&gt;// 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Binary search is &lt;strong&gt;O(log n)&lt;/strong&gt; because each comparison eliminates about half of the remaining sorted range. It takes around 20 comparisons to search one million sorted values, while a linear search may need to inspect all one million. The input must already be sorted for binary search to work.&lt;/p&gt;

&lt;p&gt;Complexity can describe memory as well as time. The &lt;code&gt;sum&lt;/code&gt; function uses &lt;strong&gt;O(1)&lt;/strong&gt; extra space because it keeps only one running total. Copying an array before processing it, by contrast, requires &lt;strong&gt;O(n)&lt;/strong&gt; additional space. For a particular algorithm, best-, average-, and worst-case complexity may differ: Quick Sort, for example, averages &lt;strong&gt;O(n log n)&lt;/strong&gt; time but can take &lt;strong&gt;O(n²)&lt;/strong&gt; in its worst case. These examples and runnable search and duplicate-check implementations are available in &lt;code&gt;code/algorithm-complexity-in-javascript.js&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search algorithms: Linear vs Binary
&lt;/h2&gt;

&lt;p&gt;Searching means locating a value in a collection and, often, returning its index. The right algorithm depends on how the data is arranged, how often it will be searched, and whether that arrangement can be maintained. Linear search works on any array. Binary search can be much faster, but it only works correctly when the array is sorted according to the same ordering used by the comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linear search: inspect items in order
&lt;/h3&gt;

&lt;p&gt;A linear search starts at the first element and checks each value until it finds a match or reaches the end. It does not need preprocessing, and it works equally well on sorted and unsorted data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;linearSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Visit each element from left to right.&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Return immediately when this element is the target.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// No element matched the target.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsortedScores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;linearSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedScores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;linearSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedScores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the target is first, the search takes &lt;strong&gt;O(1)&lt;/strong&gt; time. If it is last or absent, every element must be checked, so the worst-case time is &lt;strong&gt;O(n)&lt;/strong&gt;; an unsuccessful search also takes O(n). The implementation uses &lt;strong&gt;O(1)&lt;/strong&gt; extra space. When duplicates exist, this version returns the index of the first matching value encountered from the left. Linear search is often the simplest choice for small lists, changing data, or a single lookup where sorting first would cost more than scanning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binary search: halve a sorted range
&lt;/h3&gt;

&lt;p&gt;Binary search keeps a range of possible positions. It compares the target with the middle element; if they differ, sorted order tells it which half cannot contain the target. Repeating that step reduces the remaining range by roughly half each time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Continue while at least one candidate index remains.&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Find the middle without adding the two bounds directly.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;high&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// This returns a matching index; duplicates may have other matching indexes.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// The target can only be in the portion to the right.&lt;/span&gt;
      &lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// The target can only be in the portion to the left.&lt;/span&gt;
      &lt;span class="nx"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// The candidate range is empty, so the target is not present.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedScores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedScores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedScores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The array must remain sorted in ascending order for this implementation. On each iteration, the bounds move past the middle index, ensuring that the search makes progress and does not examine that same element again. An empty array is handled naturally because its initial range has &lt;code&gt;low&lt;/code&gt; greater than &lt;code&gt;high&lt;/code&gt;. Binary search takes &lt;strong&gt;O(log n)&lt;/strong&gt; time in the best, average, and worst cases: even for one million items, it needs only about 20 comparisons. It uses &lt;strong&gt;O(1)&lt;/strong&gt; extra space because this iterative version does not create subarrays or use recursion.&lt;/p&gt;

&lt;p&gt;There are two details to consider when adopting binary search. First, it does not necessarily return the first occurrence when duplicates are present; the example returns whichever matching middle element it encounters. If the requirement is specifically the first or last duplicate, adjust the algorithm to keep searching the appropriate half after a match. Second, keeping data sorted has a cost. Sorting an unsorted array usually takes &lt;strong&gt;O(n log n)&lt;/strong&gt; time, and inserting into the middle of a JavaScript array can take O(n) because later elements must move. For one search, a linear scan may therefore be cheaper. For many searches against a mostly static, already-sorted array, binary search can substantially reduce lookup work.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Data requirement&lt;/th&gt;
&lt;th&gt;Worst-case search time&lt;/th&gt;
&lt;th&gt;Useful when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linear search&lt;/td&gt;
&lt;td&gt;Any order&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;The collection is small, unsorted, or searched infrequently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary search&lt;/td&gt;
&lt;td&gt;Sorted by the searched value&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;The sorted collection is searched repeatedly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In practice, choose the algorithm based on the full data lifecycle, not just the lookup step. If the collection changes often, the work of preserving sorted order can outweigh faster searches. If it is stable and searched frequently, paying once to sort and then using binary search may be a good trade-off. For lookups by a unique key in a frequently changing in-memory collection, a &lt;code&gt;Map&lt;/code&gt; may be a more suitable structure than either repeated scanning or maintaining a sorted array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-world use cases
&lt;/h2&gt;

&lt;p&gt;Sorting algorithms are only part of everyday data processing. Interfaces and services also search collections, select records using several fields, and arrange nested objects for display. Built-in array methods express these tasks clearly; knowing the cost of their scans helps you decide when they are sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching an array for a record
&lt;/h3&gt;

&lt;p&gt;For a small in-memory collection, &lt;code&gt;find()&lt;/code&gt; is a direct way to retrieve the first record with a matching identifier. It returns &lt;code&gt;undefined&lt;/code&gt; when no record matches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-101&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Notebook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;6.5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-102&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.25&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-103&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk lamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;24.0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;findProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;findProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-102&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// { id: "p-102", name: "Pen", price: 1.25 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;findProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-999&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a linear search: the worst case checks every item, so the time grows as O(n), while the search itself uses O(1) extra space. It is usually a sensible choice for a modest list or an occasional lookup. If an application repeatedly looks up items by ID in a large collection, a &lt;code&gt;Map&lt;/code&gt; built once can provide typically O(1) lookups, at the cost of extra memory and keeping the map synchronized with changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filtering and sorting complex objects
&lt;/h3&gt;

&lt;p&gt;Real data often contains nested objects and arrays. For example, an order list can be filtered by a customer's name and by whether an order includes a requested product, then sorted by total:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;o-501&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avery Chen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Notebook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;16.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;o-502&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jordan Rivera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk lamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;24.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;o-503&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avery Chen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;findOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customerQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customerQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;productQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customerMatches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productMatches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;customerMatches&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productMatches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;findOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avery&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// ["o-503", "o-501"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;filter()&lt;/code&gt; checks each order, while &lt;code&gt;some()&lt;/code&gt; stops checking an order's items as soon as it finds a match. In the worst case, the scan examines every item across every order. &lt;code&gt;filter()&lt;/code&gt; creates a new array, so sorting its result does not rearrange the original &lt;code&gt;orders&lt;/code&gt; array. The records themselves are shared, however; this example only reads them. If nested fields may be missing or have inconsistent types, validate or normalize them when data enters the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer the built-in sort for application code
&lt;/h2&gt;

&lt;p&gt;In ordinary JavaScript programs, prefer &lt;code&gt;Array.prototype.sort()&lt;/code&gt; unless there is a specific reason to implement a custom algorithm. Supply a comparator for numeric ordering: without one, the default comparison is lexicographic, so numbers can be ordered like strings rather than by numeric value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2, 10]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [10, 2, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort()&lt;/code&gt; mutates the array it is called on, which is why the example sorts a copy. For custom implementations, test empty and single-element arrays, sorted and reverse-sorted input, duplicates, and negative values. Confirm both the sorted result and the intended mutation behavior.&lt;/p&gt;

&lt;p&gt;Bubble Sort teaches how repeated local changes can produce a global result. Quick Sort shows how partitioning can reduce a problem into smaller ones. Understanding their steps, invariants, and complexity helps you recognize the cost of an algorithm—and choose an appropriate tool instead of relying on a single example's performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: choosing for real-world performance
&lt;/h2&gt;

&lt;p&gt;For most JavaScript applications, start with the built-in &lt;code&gt;Array.prototype.sort()&lt;/code&gt; and a comparator that matches the data. It is optimized by the runtime and is easier to maintain than a hand-written sorting algorithm. If the array should remain unchanged, sort a copy or use &lt;code&gt;toSorted()&lt;/code&gt; where the supported runtime provides it. Choose another approach only when a measured requirement—such as predictable worst-case time, stability, memory use, or repeated lookups—calls for it.&lt;/p&gt;

&lt;p&gt;Bubble Sort is appropriate for learning, or occasionally for a tiny collection where simplicity matters more than speed. Its O(n²) average and worst-case time makes it a poor choice as data grows. Quick Sort illustrates why divide-and-conquer algorithms often perform better on larger collections: its average time is O(n log n). But its worst case is O(n²), and the simple implementation here is not stable, so it is not automatically the best production choice.&lt;/p&gt;

&lt;p&gt;In practice, choose based on the workload and the guarantees the application needs. For frequent lookups by key, build a &lt;code&gt;Map&lt;/code&gt; rather than repeatedly scanning an array; for large datasets, consider whether sorting should happen in a database or on a server rather than blocking the browser's main thread. Measure with representative data, including already sorted input, duplicates, and unfavorable cases, and account for copying and memory as well as elapsed time. The fastest algorithm on a small benchmark is not necessarily the right choice if it violates ordering requirements or becomes costly to maintain.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Écrire un article complet sur les algorhytme en JavaScriptavec exemples de code, explications claires et cas d'usage réels. - 1792338198507</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:43:19 +0000</pubDate>
      <link>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-1fkj</link>
      <guid>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-1fkj</guid>
      <description>&lt;h1&gt;
  
  
  Debouncing vs. Throttling in JavaScript: How to Choose
&lt;/h1&gt;

&lt;p&gt;JavaScript interfaces often receive events faster than they need to perform useful work. A search field emits an &lt;code&gt;input&lt;/code&gt; event for every character. A scroll listener may run many times during a single movement, and dragging a slider produces a stream of changing values. If each event triggers an expensive calculation, layout update, or network request, the application can waste resources and feel sluggish.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling both limit how often a callback runs, but they answer different questions. &lt;strong&gt;Debouncing asks whether activity has paused long enough to act. Throttling asks whether enough time has passed to act again.&lt;/strong&gt; That distinction determines which technique suits an interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debouncing: wait for a pause
&lt;/h2&gt;

&lt;p&gt;A trailing-edge debounce starts a timer whenever its wrapper is called. Each new call clears and restarts that timer. The callback runs after the specified quiet period has passed with no new calls, typically once with the arguments from the latest call.&lt;/p&gt;

&lt;p&gt;Imagine a search box configured with a 300-millisecond delay. If a user types a character every 100 milliseconds, each character resets the timer. No search begins while typing continues. After the user pauses for 300 milliseconds, one search starts with the complete query. The intermediate queries are obsolete, so discarding them is desirable.&lt;/p&gt;

&lt;p&gt;This makes debounce useful when the final state matters more than intermediate states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search suggestions and autocomplete&lt;/li&gt;
&lt;li&gt;Validation after someone finishes editing a field&lt;/li&gt;
&lt;li&gt;Filtering a list after the query changes&lt;/li&gt;
&lt;li&gt;Autosaving a draft after edits pause&lt;/li&gt;
&lt;li&gt;Recalculating a result after several related controls settle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that continuous activity can postpone a trailing debounce indefinitely. A preview debounced during a long drag may not update until the pointer stops. Some debounce utilities offer &lt;code&gt;maxWait&lt;/code&gt;, which guarantees an invocation after a maximum elapsed time even if calls continue. When ongoing progress is important, however, throttling is often easier to reason about.&lt;/p&gt;

&lt;p&gt;Debounce may also use &lt;strong&gt;leading-edge&lt;/strong&gt; behavior: it invokes immediately on the first call, then suppresses or delays subsequent calls. Some implementations support both leading and trailing invocations. These options change the user experience, so specify the desired edge behavior rather than assuming all debounce functions work alike. Search commonly uses trailing behavior; an action that should respond immediately but resist repeated activation may use a leading policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Throttling: limit the rate
&lt;/h2&gt;

&lt;p&gt;A throttle permits a callback to run at most once during each configured interval. Calls that arrive before the interval ends may be ignored, or combined into a trailing invocation with the latest arguments. Unlike a trailing debounce, a throttle can keep producing updates while events continue.&lt;/p&gt;

&lt;p&gt;For example, a scroll handler that updates a reading-progress indicator could run at most once every 100 milliseconds. The browser may emit many scroll events within that time, but the indicator still receives regular updates without doing the same work for every event.&lt;/p&gt;

&lt;p&gt;Throttling is a good fit when intermediate progress is useful but processing every intermediate value is unnecessary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll position indicators and scroll-driven interface updates&lt;/li&gt;
&lt;li&gt;Pointer or drag previews&lt;/li&gt;
&lt;li&gt;Resize feedback while a window is being resized&lt;/li&gt;
&lt;li&gt;Progress reporting and sampling telemetry&lt;/li&gt;
&lt;li&gt;Repeated actions that should have a minimum interval between executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Throttle implementations also have edge policies. A &lt;strong&gt;leading&lt;/strong&gt; throttle runs immediately when a call arrives after an idle interval. A &lt;strong&gt;trailing&lt;/strong&gt; throttle runs at the end of the interval if calls arrived, usually using the latest call's arguments. A leading-and-trailing throttle gives an immediate response and a final update for the burst. A leading-only throttle can miss the final value; a trailing-only throttle delays the first response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timing difference
&lt;/h2&gt;

&lt;p&gt;Consider calls at 0, 80, 160, and 200 milliseconds with a 200-millisecond wait. A trailing debounce restarts its timer on every call, so it runs around 400 milliseconds, after the quiet period begins. A leading throttle runs immediately at 0 and discards calls inside its interval. A leading-and-trailing throttle runs immediately and then around 200 milliseconds with the latest arguments received during that interval. The exact result depends on the chosen edge policy and timer scheduling.&lt;/p&gt;

&lt;p&gt;The event name alone does not dictate the choice. Debounce a resize event if the application only needs final dimensions after resizing; throttle it if the user should see a chart preview update while resizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple implementations
&lt;/h2&gt;

&lt;p&gt;This trailing debounce retains the most recent arguments and receiver (&lt;code&gt;this&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic leading throttle uses a timestamp and discards calls inside the interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These snippets intentionally demonstrate different common policies: the debounce is trailing-only, while the throttle is leading-only. A production utility may need explicit validation, trailing behavior, and methods such as &lt;code&gt;cancel()&lt;/code&gt; or &lt;code&gt;flush()&lt;/code&gt;. The standalone companion examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; explore those implementation details.&lt;/p&gt;

&lt;p&gt;Create a wrapper once and reuse it. Every wrapper has its own timer or timestamp state; constructing a new one for each event defeats rate control. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Searching for:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a component is removed, unregister its event listener and cancel pending work if the utility supports cancellation. Otherwise, a delayed callback may try to update an interface that no longer exists.&lt;/p&gt;

&lt;p&gt;For periodic feedback during ongoing activity, reuse a throttled wrapper instead. This example samples scroll position at most once per 100 milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Reading progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the leading-only throttle above, so it may not run once more with the final scroll position after a burst. Choose a trailing-capable implementation if that last update is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing, rendering, and asynchronous work
&lt;/h2&gt;

&lt;p&gt;Neither technique makes a callback cheaper. It only reduces how often the callback starts. If a throttled callback blocks the main thread for 200 milliseconds, limiting it to one start per 100 milliseconds cannot make the page responsive. Measure the work itself and choose an interval that matches the interaction. Search may tolerate a few hundred milliseconds; visual feedback usually needs a shorter delay.&lt;/p&gt;

&lt;p&gt;Timer delays are minimums, not exact deadlines. &lt;code&gt;setTimeout&lt;/code&gt; makes a callback eligible after the requested delay, but a busy event loop or background-tab timer throttling can make it run later. For visual updates that should align with browser painting, &lt;code&gt;requestAnimationFrame&lt;/code&gt; can coalesce work around frames. It is a rendering scheduler, not a substitute for waiting until activity stops.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling also govern when asynchronous work starts, not what happens after it starts. A debounced search request may finish after a newer request and overwrite current results. Use &lt;code&gt;AbortController&lt;/code&gt; to cancel obsolete fetches where possible, or compare request identifiers and ignore stale responses. Promise-returning callbacks are not automatically awaited or serialized by either wrapper.&lt;/p&gt;

&lt;p&gt;Finally, neither technique is suitable when every event must be preserved. Payments, audit events, or other must-not-lose operations need a queue or durable processing strategy. Debounce and throttle intentionally combine or discard calls; they do not guarantee delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing and testing
&lt;/h2&gt;

&lt;p&gt;Ask what the interface should do during a burst. If it should wait until the user pauses and then act once on the latest state, choose debounce. If it should keep reporting progress but can skip some intermediate values, choose throttle. Then decide whether the first call should happen immediately, whether a final trailing call is needed, and how pending work should be canceled.&lt;/p&gt;

&lt;p&gt;Test the timing policy rather than exact wall-clock precision. For debounce, verify that rapid calls produce one invocation with the latest arguments, separate bursts invoke separately, and cancellation suppresses pending work. For throttle, verify that invocations respect the interval and that leading and trailing behavior match the chosen policy. Fake timers make these tests deterministic. Also test receiver preservation if callbacks rely on &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both patterns are simple, but choosing the wrong one can make an interface either wasteful or unresponsive. Use debounce for settled state, throttle for periodic progress, and a queue when no event can be lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Debounce&lt;/th&gt;
&lt;th&gt;Throttle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When does it run?&lt;/td&gt;
&lt;td&gt;After calls stop for the quiet period&lt;/td&gt;
&lt;td&gt;At most once per interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens during a steady stream?&lt;/td&gt;
&lt;td&gt;A trailing call waits until activity pauses (unless &lt;code&gt;maxWait&lt;/code&gt; is set)&lt;/td&gt;
&lt;td&gt;Calls keep producing updates at a controlled rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens to intermediate calls?&lt;/td&gt;
&lt;td&gt;Usually replaced by the latest call&lt;/td&gt;
&lt;td&gt;Usually skipped or coalesced into a trailing call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Search, autosave, validation, settled filters&lt;/td&gt;
&lt;td&gt;Scroll feedback, drag previews, resize feedback, sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose it when...&lt;/td&gt;
&lt;td&gt;Only the final state matters&lt;/td&gt;
&lt;td&gt;Progress during the interaction matters&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Choose debounce for settled input and throttle for periodic feedback; use a queue if every event must be retained. If your project already uses Lodash, &lt;code&gt;_.debounce&lt;/code&gt; and &lt;code&gt;_.throttle&lt;/code&gt; provide established implementations, including options such as leading/trailing calls and cancellation (&lt;code&gt;cancel()&lt;/code&gt;; debounce also supports &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;maxWait&lt;/code&gt;). Prefer them over maintaining custom timing code when Lodash is already a dependency. For a small dependency-free utility, the standalone examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; show the core behavior. Neither Lodash nor a custom wrapper cancels asynchronous work that has already started, so handle aborts and stale responses separately.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Écrire un article complet sur les algorhytme en JavaScriptavec exemples de code, explications claires et cas d'usage réels.</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:40:15 +0000</pubDate>
      <link>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-1g3n</link>
      <guid>https://dev.to/devindev/ecrire-un-article-complet-sur-les-algorhytme-en-javascriptavec-exemples-de-code-explications-1g3n</guid>
      <description>&lt;h1&gt;
  
  
  Debouncing vs. Throttling in JavaScript: How to Choose
&lt;/h1&gt;

&lt;p&gt;JavaScript interfaces often receive events faster than they need to perform useful work. A search field emits an &lt;code&gt;input&lt;/code&gt; event for every character. A scroll listener may run many times during a single movement, and dragging a slider produces a stream of changing values. If each event triggers an expensive calculation, layout update, or network request, the application can waste resources and feel sluggish.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling both limit how often a callback runs, but they answer different questions. &lt;strong&gt;Debouncing asks whether activity has paused long enough to act. Throttling asks whether enough time has passed to act again.&lt;/strong&gt; That distinction determines which technique suits an interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debouncing: wait for a pause
&lt;/h2&gt;

&lt;p&gt;A trailing-edge debounce starts a timer whenever its wrapper is called. Each new call clears and restarts that timer. The callback runs after the specified quiet period has passed with no new calls, typically once with the arguments from the latest call.&lt;/p&gt;

&lt;p&gt;Imagine a search box configured with a 300-millisecond delay. If a user types a character every 100 milliseconds, each character resets the timer. No search begins while typing continues. After the user pauses for 300 milliseconds, one search starts with the complete query. The intermediate queries are obsolete, so discarding them is desirable.&lt;/p&gt;

&lt;p&gt;This makes debounce useful when the final state matters more than intermediate states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search suggestions and autocomplete&lt;/li&gt;
&lt;li&gt;Validation after someone finishes editing a field&lt;/li&gt;
&lt;li&gt;Filtering a list after the query changes&lt;/li&gt;
&lt;li&gt;Autosaving a draft after edits pause&lt;/li&gt;
&lt;li&gt;Recalculating a result after several related controls settle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that continuous activity can postpone a trailing debounce indefinitely. A preview debounced during a long drag may not update until the pointer stops. Some debounce utilities offer &lt;code&gt;maxWait&lt;/code&gt;, which guarantees an invocation after a maximum elapsed time even if calls continue. When ongoing progress is important, however, throttling is often easier to reason about.&lt;/p&gt;

&lt;p&gt;Debounce may also use &lt;strong&gt;leading-edge&lt;/strong&gt; behavior: it invokes immediately on the first call, then suppresses or delays subsequent calls. Some implementations support both leading and trailing invocations. These options change the user experience, so specify the desired edge behavior rather than assuming all debounce functions work alike. Search commonly uses trailing behavior; an action that should respond immediately but resist repeated activation may use a leading policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Throttling: limit the rate
&lt;/h2&gt;

&lt;p&gt;A throttle permits a callback to run at most once during each configured interval. Calls that arrive before the interval ends may be ignored, or combined into a trailing invocation with the latest arguments. Unlike a trailing debounce, a throttle can keep producing updates while events continue.&lt;/p&gt;

&lt;p&gt;For example, a scroll handler that updates a reading-progress indicator could run at most once every 100 milliseconds. The browser may emit many scroll events within that time, but the indicator still receives regular updates without doing the same work for every event.&lt;/p&gt;

&lt;p&gt;Throttling is a good fit when intermediate progress is useful but processing every intermediate value is unnecessary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll position indicators and scroll-driven interface updates&lt;/li&gt;
&lt;li&gt;Pointer or drag previews&lt;/li&gt;
&lt;li&gt;Resize feedback while a window is being resized&lt;/li&gt;
&lt;li&gt;Progress reporting and sampling telemetry&lt;/li&gt;
&lt;li&gt;Repeated actions that should have a minimum interval between executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Throttle implementations also have edge policies. A &lt;strong&gt;leading&lt;/strong&gt; throttle runs immediately when a call arrives after an idle interval. A &lt;strong&gt;trailing&lt;/strong&gt; throttle runs at the end of the interval if calls arrived, usually using the latest call's arguments. A leading-and-trailing throttle gives an immediate response and a final update for the burst. A leading-only throttle can miss the final value; a trailing-only throttle delays the first response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timing difference
&lt;/h2&gt;

&lt;p&gt;Consider calls at 0, 80, 160, and 200 milliseconds with a 200-millisecond wait. A trailing debounce restarts its timer on every call, so it runs around 400 milliseconds, after the quiet period begins. A leading throttle runs immediately at 0 and discards calls inside its interval. A leading-and-trailing throttle runs immediately and then around 200 milliseconds with the latest arguments received during that interval. The exact result depends on the chosen edge policy and timer scheduling.&lt;/p&gt;

&lt;p&gt;The event name alone does not dictate the choice. Debounce a resize event if the application only needs final dimensions after resizing; throttle it if the user should see a chart preview update while resizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple implementations
&lt;/h2&gt;

&lt;p&gt;This trailing debounce retains the most recent arguments and receiver (&lt;code&gt;this&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic leading throttle uses a timestamp and discards calls inside the interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These snippets intentionally demonstrate different common policies: the debounce is trailing-only, while the throttle is leading-only. A production utility may need explicit validation, trailing behavior, and methods such as &lt;code&gt;cancel()&lt;/code&gt; or &lt;code&gt;flush()&lt;/code&gt;. The standalone companion examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; explore those implementation details.&lt;/p&gt;

&lt;p&gt;Create a wrapper once and reuse it. Every wrapper has its own timer or timestamp state; constructing a new one for each event defeats rate control. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Searching for:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a component is removed, unregister its event listener and cancel pending work if the utility supports cancellation. Otherwise, a delayed callback may try to update an interface that no longer exists.&lt;/p&gt;

&lt;p&gt;For periodic feedback during ongoing activity, reuse a throttled wrapper instead. This example samples scroll position at most once per 100 milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Reading progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the leading-only throttle above, so it may not run once more with the final scroll position after a burst. Choose a trailing-capable implementation if that last update is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing, rendering, and asynchronous work
&lt;/h2&gt;

&lt;p&gt;Neither technique makes a callback cheaper. It only reduces how often the callback starts. If a throttled callback blocks the main thread for 200 milliseconds, limiting it to one start per 100 milliseconds cannot make the page responsive. Measure the work itself and choose an interval that matches the interaction. Search may tolerate a few hundred milliseconds; visual feedback usually needs a shorter delay.&lt;/p&gt;

&lt;p&gt;Timer delays are minimums, not exact deadlines. &lt;code&gt;setTimeout&lt;/code&gt; makes a callback eligible after the requested delay, but a busy event loop or background-tab timer throttling can make it run later. For visual updates that should align with browser painting, &lt;code&gt;requestAnimationFrame&lt;/code&gt; can coalesce work around frames. It is a rendering scheduler, not a substitute for waiting until activity stops.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling also govern when asynchronous work starts, not what happens after it starts. A debounced search request may finish after a newer request and overwrite current results. Use &lt;code&gt;AbortController&lt;/code&gt; to cancel obsolete fetches where possible, or compare request identifiers and ignore stale responses. Promise-returning callbacks are not automatically awaited or serialized by either wrapper.&lt;/p&gt;

&lt;p&gt;Finally, neither technique is suitable when every event must be preserved. Payments, audit events, or other must-not-lose operations need a queue or durable processing strategy. Debounce and throttle intentionally combine or discard calls; they do not guarantee delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing and testing
&lt;/h2&gt;

&lt;p&gt;Ask what the interface should do during a burst. If it should wait until the user pauses and then act once on the latest state, choose debounce. If it should keep reporting progress but can skip some intermediate values, choose throttle. Then decide whether the first call should happen immediately, whether a final trailing call is needed, and how pending work should be canceled.&lt;/p&gt;

&lt;p&gt;Test the timing policy rather than exact wall-clock precision. For debounce, verify that rapid calls produce one invocation with the latest arguments, separate bursts invoke separately, and cancellation suppresses pending work. For throttle, verify that invocations respect the interval and that leading and trailing behavior match the chosen policy. Fake timers make these tests deterministic. Also test receiver preservation if callbacks rely on &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both patterns are simple, but choosing the wrong one can make an interface either wasteful or unresponsive. Use debounce for settled state, throttle for periodic progress, and a queue when no event can be lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Debounce&lt;/th&gt;
&lt;th&gt;Throttle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When does it run?&lt;/td&gt;
&lt;td&gt;After calls stop for the quiet period&lt;/td&gt;
&lt;td&gt;At most once per interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens during a steady stream?&lt;/td&gt;
&lt;td&gt;A trailing call waits until activity pauses (unless &lt;code&gt;maxWait&lt;/code&gt; is set)&lt;/td&gt;
&lt;td&gt;Calls keep producing updates at a controlled rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens to intermediate calls?&lt;/td&gt;
&lt;td&gt;Usually replaced by the latest call&lt;/td&gt;
&lt;td&gt;Usually skipped or coalesced into a trailing call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Search, autosave, validation, settled filters&lt;/td&gt;
&lt;td&gt;Scroll feedback, drag previews, resize feedback, sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose it when...&lt;/td&gt;
&lt;td&gt;Only the final state matters&lt;/td&gt;
&lt;td&gt;Progress during the interaction matters&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Choose debounce for settled input and throttle for periodic feedback; use a queue if every event must be retained. If your project already uses Lodash, &lt;code&gt;_.debounce&lt;/code&gt; and &lt;code&gt;_.throttle&lt;/code&gt; provide established implementations, including options such as leading/trailing calls and cancellation (&lt;code&gt;cancel()&lt;/code&gt;; debounce also supports &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;maxWait&lt;/code&gt;). Prefer them over maintaining custom timing code when Lodash is already a dependency. For a small dependency-free utility, the standalone examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; show the core behavior. Neither Lodash nor a custom wrapper cancels asynchronous work that has already started, so handle aborts and stale responses separately.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Écrire un article sur les Web Workers en JavaScript</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:32:45 +0000</pubDate>
      <link>https://dev.to/devindev/ecrire-un-article-sur-les-web-workers-en-javascript-33j5</link>
      <guid>https://dev.to/devindev/ecrire-un-article-sur-les-web-workers-en-javascript-33j5</guid>
      <description>&lt;h1&gt;
  
  
  Debouncing vs. Throttling in JavaScript: How to Choose
&lt;/h1&gt;

&lt;p&gt;JavaScript interfaces often receive events faster than they need to perform useful work. A search field emits an &lt;code&gt;input&lt;/code&gt; event for every character. A scroll listener may run many times during a single movement, and dragging a slider produces a stream of changing values. If each event triggers an expensive calculation, layout update, or network request, the application can waste resources and feel sluggish.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling both limit how often a callback runs, but they answer different questions. &lt;strong&gt;Debouncing asks whether activity has paused long enough to act. Throttling asks whether enough time has passed to act again.&lt;/strong&gt; That distinction determines which technique suits an interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debouncing: wait for a pause
&lt;/h2&gt;

&lt;p&gt;A trailing-edge debounce starts a timer whenever its wrapper is called. Each new call clears and restarts that timer. The callback runs after the specified quiet period has passed with no new calls, typically once with the arguments from the latest call.&lt;/p&gt;

&lt;p&gt;Imagine a search box configured with a 300-millisecond delay. If a user types a character every 100 milliseconds, each character resets the timer. No search begins while typing continues. After the user pauses for 300 milliseconds, one search starts with the complete query. The intermediate queries are obsolete, so discarding them is desirable.&lt;/p&gt;

&lt;p&gt;This makes debounce useful when the final state matters more than intermediate states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search suggestions and autocomplete&lt;/li&gt;
&lt;li&gt;Validation after someone finishes editing a field&lt;/li&gt;
&lt;li&gt;Filtering a list after the query changes&lt;/li&gt;
&lt;li&gt;Autosaving a draft after edits pause&lt;/li&gt;
&lt;li&gt;Recalculating a result after several related controls settle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that continuous activity can postpone a trailing debounce indefinitely. A preview debounced during a long drag may not update until the pointer stops. Some debounce utilities offer &lt;code&gt;maxWait&lt;/code&gt;, which guarantees an invocation after a maximum elapsed time even if calls continue. When ongoing progress is important, however, throttling is often easier to reason about.&lt;/p&gt;

&lt;p&gt;Debounce may also use &lt;strong&gt;leading-edge&lt;/strong&gt; behavior: it invokes immediately on the first call, then suppresses or delays subsequent calls. Some implementations support both leading and trailing invocations. These options change the user experience, so specify the desired edge behavior rather than assuming all debounce functions work alike. Search commonly uses trailing behavior; an action that should respond immediately but resist repeated activation may use a leading policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Throttling: limit the rate
&lt;/h2&gt;

&lt;p&gt;A throttle permits a callback to run at most once during each configured interval. Calls that arrive before the interval ends may be ignored, or combined into a trailing invocation with the latest arguments. Unlike a trailing debounce, a throttle can keep producing updates while events continue.&lt;/p&gt;

&lt;p&gt;For example, a scroll handler that updates a reading-progress indicator could run at most once every 100 milliseconds. The browser may emit many scroll events within that time, but the indicator still receives regular updates without doing the same work for every event.&lt;/p&gt;

&lt;p&gt;Throttling is a good fit when intermediate progress is useful but processing every intermediate value is unnecessary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll position indicators and scroll-driven interface updates&lt;/li&gt;
&lt;li&gt;Pointer or drag previews&lt;/li&gt;
&lt;li&gt;Resize feedback while a window is being resized&lt;/li&gt;
&lt;li&gt;Progress reporting and sampling telemetry&lt;/li&gt;
&lt;li&gt;Repeated actions that should have a minimum interval between executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Throttle implementations also have edge policies. A &lt;strong&gt;leading&lt;/strong&gt; throttle runs immediately when a call arrives after an idle interval. A &lt;strong&gt;trailing&lt;/strong&gt; throttle runs at the end of the interval if calls arrived, usually using the latest call's arguments. A leading-and-trailing throttle gives an immediate response and a final update for the burst. A leading-only throttle can miss the final value; a trailing-only throttle delays the first response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timing difference
&lt;/h2&gt;

&lt;p&gt;Consider calls at 0, 80, 160, and 200 milliseconds with a 200-millisecond wait. A trailing debounce restarts its timer on every call, so it runs around 400 milliseconds, after the quiet period begins. A leading throttle runs immediately at 0 and discards calls inside its interval. A leading-and-trailing throttle runs immediately and then around 200 milliseconds with the latest arguments received during that interval. The exact result depends on the chosen edge policy and timer scheduling.&lt;/p&gt;

&lt;p&gt;The event name alone does not dictate the choice. Debounce a resize event if the application only needs final dimensions after resizing; throttle it if the user should see a chart preview update while resizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple implementations
&lt;/h2&gt;

&lt;p&gt;This trailing debounce retains the most recent arguments and receiver (&lt;code&gt;this&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic leading throttle uses a timestamp and discards calls inside the interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These snippets intentionally demonstrate different common policies: the debounce is trailing-only, while the throttle is leading-only. A production utility may need explicit validation, trailing behavior, and methods such as &lt;code&gt;cancel()&lt;/code&gt; or &lt;code&gt;flush()&lt;/code&gt;. The standalone companion examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; explore those implementation details.&lt;/p&gt;

&lt;p&gt;Create a wrapper once and reuse it. Every wrapper has its own timer or timestamp state; constructing a new one for each event defeats rate control. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Searching for:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a component is removed, unregister its event listener and cancel pending work if the utility supports cancellation. Otherwise, a delayed callback may try to update an interface that no longer exists.&lt;/p&gt;

&lt;p&gt;For periodic feedback during ongoing activity, reuse a throttled wrapper instead. This example samples scroll position at most once per 100 milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Reading progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the leading-only throttle above, so it may not run once more with the final scroll position after a burst. Choose a trailing-capable implementation if that last update is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing, rendering, and asynchronous work
&lt;/h2&gt;

&lt;p&gt;Neither technique makes a callback cheaper. It only reduces how often the callback starts. If a throttled callback blocks the main thread for 200 milliseconds, limiting it to one start per 100 milliseconds cannot make the page responsive. Measure the work itself and choose an interval that matches the interaction. Search may tolerate a few hundred milliseconds; visual feedback usually needs a shorter delay.&lt;/p&gt;

&lt;p&gt;Timer delays are minimums, not exact deadlines. &lt;code&gt;setTimeout&lt;/code&gt; makes a callback eligible after the requested delay, but a busy event loop or background-tab timer throttling can make it run later. For visual updates that should align with browser painting, &lt;code&gt;requestAnimationFrame&lt;/code&gt; can coalesce work around frames. It is a rendering scheduler, not a substitute for waiting until activity stops.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling also govern when asynchronous work starts, not what happens after it starts. A debounced search request may finish after a newer request and overwrite current results. Use &lt;code&gt;AbortController&lt;/code&gt; to cancel obsolete fetches where possible, or compare request identifiers and ignore stale responses. Promise-returning callbacks are not automatically awaited or serialized by either wrapper.&lt;/p&gt;

&lt;p&gt;Finally, neither technique is suitable when every event must be preserved. Payments, audit events, or other must-not-lose operations need a queue or durable processing strategy. Debounce and throttle intentionally combine or discard calls; they do not guarantee delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing and testing
&lt;/h2&gt;

&lt;p&gt;Ask what the interface should do during a burst. If it should wait until the user pauses and then act once on the latest state, choose debounce. If it should keep reporting progress but can skip some intermediate values, choose throttle. Then decide whether the first call should happen immediately, whether a final trailing call is needed, and how pending work should be canceled.&lt;/p&gt;

&lt;p&gt;Test the timing policy rather than exact wall-clock precision. For debounce, verify that rapid calls produce one invocation with the latest arguments, separate bursts invoke separately, and cancellation suppresses pending work. For throttle, verify that invocations respect the interval and that leading and trailing behavior match the chosen policy. Fake timers make these tests deterministic. Also test receiver preservation if callbacks rely on &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both patterns are simple, but choosing the wrong one can make an interface either wasteful or unresponsive. Use debounce for settled state, throttle for periodic progress, and a queue when no event can be lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Debounce&lt;/th&gt;
&lt;th&gt;Throttle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When does it run?&lt;/td&gt;
&lt;td&gt;After calls stop for the quiet period&lt;/td&gt;
&lt;td&gt;At most once per interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens during a steady stream?&lt;/td&gt;
&lt;td&gt;A trailing call waits until activity pauses (unless &lt;code&gt;maxWait&lt;/code&gt; is set)&lt;/td&gt;
&lt;td&gt;Calls keep producing updates at a controlled rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens to intermediate calls?&lt;/td&gt;
&lt;td&gt;Usually replaced by the latest call&lt;/td&gt;
&lt;td&gt;Usually skipped or coalesced into a trailing call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Search, autosave, validation, settled filters&lt;/td&gt;
&lt;td&gt;Scroll feedback, drag previews, resize feedback, sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose it when...&lt;/td&gt;
&lt;td&gt;Only the final state matters&lt;/td&gt;
&lt;td&gt;Progress during the interaction matters&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Choose debounce for settled input and throttle for periodic feedback; use a queue if every event must be retained. If your project already uses Lodash, &lt;code&gt;_.debounce&lt;/code&gt; and &lt;code&gt;_.throttle&lt;/code&gt; provide established implementations, including options such as leading/trailing calls and cancellation (&lt;code&gt;cancel()&lt;/code&gt;; debounce also supports &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;maxWait&lt;/code&gt;). Prefer them over maintaining custom timing code when Lodash is already a dependency. For a small dependency-free utility, the standalone examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; show the core behavior. Neither Lodash nor a custom wrapper cancels asynchronous work that has already started, so handle aborts and stale responses separately.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>Debouncing vs Throttling in JavaScript</title>
      <dc:creator>Devin</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:27:49 +0000</pubDate>
      <link>https://dev.to/devindev/debouncing-vs-throttling-in-javascript-5e5f</link>
      <guid>https://dev.to/devindev/debouncing-vs-throttling-in-javascript-5e5f</guid>
      <description>&lt;h1&gt;
  
  
  Debouncing vs. Throttling in JavaScript: How to Choose
&lt;/h1&gt;

&lt;p&gt;JavaScript interfaces often receive events faster than they need to perform useful work. A search field emits an &lt;code&gt;input&lt;/code&gt; event for every character. A scroll listener may run many times during a single movement, and dragging a slider produces a stream of changing values. If each event triggers an expensive calculation, layout update, or network request, the application can waste resources and feel sluggish.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling both limit how often a callback runs, but they answer different questions. &lt;strong&gt;Debouncing asks whether activity has paused long enough to act. Throttling asks whether enough time has passed to act again.&lt;/strong&gt; That distinction determines which technique suits an interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debouncing: wait for a pause
&lt;/h2&gt;

&lt;p&gt;A trailing-edge debounce starts a timer whenever its wrapper is called. Each new call clears and restarts that timer. The callback runs after the specified quiet period has passed with no new calls, typically once with the arguments from the latest call.&lt;/p&gt;

&lt;p&gt;Imagine a search box configured with a 300-millisecond delay. If a user types a character every 100 milliseconds, each character resets the timer. No search begins while typing continues. After the user pauses for 300 milliseconds, one search starts with the complete query. The intermediate queries are obsolete, so discarding them is desirable.&lt;/p&gt;

&lt;p&gt;This makes debounce useful when the final state matters more than intermediate states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search suggestions and autocomplete&lt;/li&gt;
&lt;li&gt;Validation after someone finishes editing a field&lt;/li&gt;
&lt;li&gt;Filtering a list after the query changes&lt;/li&gt;
&lt;li&gt;Autosaving a draft after edits pause&lt;/li&gt;
&lt;li&gt;Recalculating a result after several related controls settle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that continuous activity can postpone a trailing debounce indefinitely. A preview debounced during a long drag may not update until the pointer stops. Some debounce utilities offer &lt;code&gt;maxWait&lt;/code&gt;, which guarantees an invocation after a maximum elapsed time even if calls continue. When ongoing progress is important, however, throttling is often easier to reason about.&lt;/p&gt;

&lt;p&gt;Debounce may also use &lt;strong&gt;leading-edge&lt;/strong&gt; behavior: it invokes immediately on the first call, then suppresses or delays subsequent calls. Some implementations support both leading and trailing invocations. These options change the user experience, so specify the desired edge behavior rather than assuming all debounce functions work alike. Search commonly uses trailing behavior; an action that should respond immediately but resist repeated activation may use a leading policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Throttling: limit the rate
&lt;/h2&gt;

&lt;p&gt;A throttle permits a callback to run at most once during each configured interval. Calls that arrive before the interval ends may be ignored, or combined into a trailing invocation with the latest arguments. Unlike a trailing debounce, a throttle can keep producing updates while events continue.&lt;/p&gt;

&lt;p&gt;For example, a scroll handler that updates a reading-progress indicator could run at most once every 100 milliseconds. The browser may emit many scroll events within that time, but the indicator still receives regular updates without doing the same work for every event.&lt;/p&gt;

&lt;p&gt;Throttling is a good fit when intermediate progress is useful but processing every intermediate value is unnecessary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll position indicators and scroll-driven interface updates&lt;/li&gt;
&lt;li&gt;Pointer or drag previews&lt;/li&gt;
&lt;li&gt;Resize feedback while a window is being resized&lt;/li&gt;
&lt;li&gt;Progress reporting and sampling telemetry&lt;/li&gt;
&lt;li&gt;Repeated actions that should have a minimum interval between executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Throttle implementations also have edge policies. A &lt;strong&gt;leading&lt;/strong&gt; throttle runs immediately when a call arrives after an idle interval. A &lt;strong&gt;trailing&lt;/strong&gt; throttle runs at the end of the interval if calls arrived, usually using the latest call's arguments. A leading-and-trailing throttle gives an immediate response and a final update for the burst. A leading-only throttle can miss the final value; a trailing-only throttle delays the first response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timing difference
&lt;/h2&gt;

&lt;p&gt;Consider calls at 0, 80, 160, and 200 milliseconds with a 200-millisecond wait. A trailing debounce restarts its timer on every call, so it runs around 400 milliseconds, after the quiet period begins. A leading throttle runs immediately at 0 and discards calls inside its interval. A leading-and-trailing throttle runs immediately and then around 200 milliseconds with the latest arguments received during that interval. The exact result depends on the chosen edge policy and timer scheduling.&lt;/p&gt;

&lt;p&gt;The event name alone does not dictate the choice. Debounce a resize event if the application only needs final dimensions after resizing; throttle it if the user should see a chart preview update while resizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple implementations
&lt;/h2&gt;

&lt;p&gt;This trailing debounce retains the most recent arguments and receiver (&lt;code&gt;this&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic leading throttle uses a timestamp and discards calls inside the interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;lastCallTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These snippets intentionally demonstrate different common policies: the debounce is trailing-only, while the throttle is leading-only. A production utility may need explicit validation, trailing behavior, and methods such as &lt;code&gt;cancel()&lt;/code&gt; or &lt;code&gt;flush()&lt;/code&gt;. The standalone companion examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; explore those implementation details.&lt;/p&gt;

&lt;p&gt;Create a wrapper once and reuse it. Every wrapper has its own timer or timestamp state; constructing a new one for each event defeats rate control. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Searching for:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a component is removed, unregister its event listener and cancel pending work if the utility supports cancellation. Otherwise, a delayed callback may try to update an interface that no longer exists.&lt;/p&gt;

&lt;p&gt;For periodic feedback during ongoing activity, reuse a throttled wrapper instead. This example samples scroll position at most once per 100 milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scrollableHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Reading progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateScrollProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the leading-only throttle above, so it may not run once more with the final scroll position after a burst. Choose a trailing-capable implementation if that last update is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing, rendering, and asynchronous work
&lt;/h2&gt;

&lt;p&gt;Neither technique makes a callback cheaper. It only reduces how often the callback starts. If a throttled callback blocks the main thread for 200 milliseconds, limiting it to one start per 100 milliseconds cannot make the page responsive. Measure the work itself and choose an interval that matches the interaction. Search may tolerate a few hundred milliseconds; visual feedback usually needs a shorter delay.&lt;/p&gt;

&lt;p&gt;Timer delays are minimums, not exact deadlines. &lt;code&gt;setTimeout&lt;/code&gt; makes a callback eligible after the requested delay, but a busy event loop or background-tab timer throttling can make it run later. For visual updates that should align with browser painting, &lt;code&gt;requestAnimationFrame&lt;/code&gt; can coalesce work around frames. It is a rendering scheduler, not a substitute for waiting until activity stops.&lt;/p&gt;

&lt;p&gt;Debouncing and throttling also govern when asynchronous work starts, not what happens after it starts. A debounced search request may finish after a newer request and overwrite current results. Use &lt;code&gt;AbortController&lt;/code&gt; to cancel obsolete fetches where possible, or compare request identifiers and ignore stale responses. Promise-returning callbacks are not automatically awaited or serialized by either wrapper.&lt;/p&gt;

&lt;p&gt;Finally, neither technique is suitable when every event must be preserved. Payments, audit events, or other must-not-lose operations need a queue or durable processing strategy. Debounce and throttle intentionally combine or discard calls; they do not guarantee delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing and testing
&lt;/h2&gt;

&lt;p&gt;Ask what the interface should do during a burst. If it should wait until the user pauses and then act once on the latest state, choose debounce. If it should keep reporting progress but can skip some intermediate values, choose throttle. Then decide whether the first call should happen immediately, whether a final trailing call is needed, and how pending work should be canceled.&lt;/p&gt;

&lt;p&gt;Test the timing policy rather than exact wall-clock precision. For debounce, verify that rapid calls produce one invocation with the latest arguments, separate bursts invoke separately, and cancellation suppresses pending work. For throttle, verify that invocations respect the interval and that leading and trailing behavior match the chosen policy. Fake timers make these tests deterministic. Also test receiver preservation if callbacks rely on &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both patterns are simple, but choosing the wrong one can make an interface either wasteful or unresponsive. Use debounce for settled state, throttle for periodic progress, and a queue when no event can be lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Debounce&lt;/th&gt;
&lt;th&gt;Throttle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When does it run?&lt;/td&gt;
&lt;td&gt;After calls stop for the quiet period&lt;/td&gt;
&lt;td&gt;At most once per interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens during a steady stream?&lt;/td&gt;
&lt;td&gt;A trailing call waits until activity pauses (unless &lt;code&gt;maxWait&lt;/code&gt; is set)&lt;/td&gt;
&lt;td&gt;Calls keep producing updates at a controlled rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What happens to intermediate calls?&lt;/td&gt;
&lt;td&gt;Usually replaced by the latest call&lt;/td&gt;
&lt;td&gt;Usually skipped or coalesced into a trailing call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Search, autosave, validation, settled filters&lt;/td&gt;
&lt;td&gt;Scroll feedback, drag previews, resize feedback, sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose it when...&lt;/td&gt;
&lt;td&gt;Only the final state matters&lt;/td&gt;
&lt;td&gt;Progress during the interaction matters&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Choose debounce for settled input and throttle for periodic feedback; use a queue if every event must be retained. If your project already uses Lodash, &lt;code&gt;_.debounce&lt;/code&gt; and &lt;code&gt;_.throttle&lt;/code&gt; provide established implementations, including options such as leading/trailing calls and cancellation (&lt;code&gt;cancel()&lt;/code&gt;; debounce also supports &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;maxWait&lt;/code&gt;). Prefer them over maintaining custom timing code when Lodash is already a dependency. For a small dependency-free utility, the standalone examples in &lt;a href="//../code/"&gt;&lt;code&gt;code/&lt;/code&gt;&lt;/a&gt; show the core behavior. Neither Lodash nor a custom wrapper cancels asynchronous work that has already started, so handle aborts and stale responses separately.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
