JavaScript String Bevat Substring: De volledige gids

13 februari 2026

Controleren of de ene tekenreeks de andere bevat (zoeken naar een deelreeks) blijft een van de meest voorkomende bewerkingen met tekenreeksen bij het ontwikkelen in JavaScript. Of je nu gebruikersinvoer valideert, zoekfilters implementeert in React-/Vue-apps, API-responsen parseert, functies voor automatisch aanvullen bouwt of logbestanden verwerkt in Node.js: deze controle komt overal voor.

Vanaf februari 2026 is ECMAScript 2026 (ES2026) de huidige of aanstaande standaard (definitief vastgesteld medio 2026). De kern String.prototype methoden voor het opsporen van deelstrings — includes(), indexOf(), search(), en reguliere expressies .test() — blijven ongewijzigd vanaf ES2015/ES6. Er zijn geen belangrijke nieuwe zoekmethoden voor strings toegevoegd in ES2025 of ES2026; de focus blijft liggen op prestaties, leesbaarheid, Unicode-correctheid en moderne best practices in engines zoals V8 (Node 22+/Chrome 130+), SpiderMonkey (Firefox 135+) en JavaScriptCore (Safari 19+).

Deze gids behandelt alle praktische technieken, de prestatie-eisen in 2026, uitzonderingsgevallen, beveiligingsoverwegingen en aanbevelingen die direct in de productie kunnen worden toegepast.

Waarom controles op subreeksen overal voorkomen

  • UI/UX: Live zoeken, filteren op tags, formuliervalidatie
  • Backend: Logboekanalyse, routevergelijking, inhoudsmoderatie
  • Gegevensverwerking: Arrays met tekenreeksen/objecten filteren
  • Beveiliging: Het opsporen van schadelijke patronen (XSS-payloads, verboden woorden)
  • Prestatiegevoelig: Automatisch aanvullen (miljoenen controles per seconde), realtime monitoring

Kleine inefficiënties stapelen zich snel op in lussen of bij grote datasets.

1. Moderne standaard: String.prototype.includes()

De standaardmethode sinds ES2015 — overzichtelijk, duidelijk en sterk geoptimaliseerd.

Handtekening

js
str.includes(zoektekst, positie?)
  • zoekterm: te zoeken substring (omgezet naar string; RegExp genereert een fout)
  • functie (optioneel): startindex (standaard 0; beperkt tot ≥0)

Retourzendingen: booleaanse waarde

Voorbeelden

js
const phrase = "JavaScript is in 2026 krachtig en snel";
console.log(phrase.includes("2026"));          // waar
console.log(phrase.includes("2025"));          // false
console.log(phrase.includes("script"));        // true (hoofdlettergevoelig)
console.log(phrase.includes(""));              // true  ← 'empty' komt altijd overeen
console.log(phrase.includes("fast", 30));      // waar
console.log(phrase.includes("fast", 40));      // false

Waarom kiezen voor omvat() in 2026?

  • Maximale duidelijkheid: geeft duidelijk weer of het iets bevat“
  • Geoptimaliseerd voor de engine (V8/SpiderMonkey maken gebruik van snelle Boyer-Moore- of tweerichtingsalgoritmen)
  • Universele ondersteuning: 100% in moderne browsers/Node sinds circa 2017

Nadelen

  • Alleen booleaanse waarden (geen index)
  • Altijd hoofdlettergevoelig

2. Klassiek en positiegevoelig: String.prototype.indexOf()

Een werkpaard uit de tijd vóór ES6 — nog steeds uitstekend als je de locatie nodig hebt.

Handtekening

js
str.indexOf(searchString, fromIndex?)

Retourzendingen: eerste index ≥ vanafIndex of -1

Bestaande controle

js
if (phrase.indexOf("2026") !== -1) { /* gevonden */ }
// Aanbevolen stijl:
if (phrase.indexOf("2026") >= 0) { /* gevonden */ }

Alle resultaten weergeven

js
let posities = [];
let idx = -1;
while ((idx = phrase.indexOf("a", idx + 1)) !== -1) {
  posities.push(idx);
}
console.log(posities);  // [1, 4, 11, ...]

De realiteit van 2026: omvat() en indexOf() hebben vrijwel dezelfde snelheid bij booleaanse controles — kies omvat() voor de duidelijkheid, tenzij je de index nodig hebt.

3. Controles waarbij hoofdletters en kleine letters niet van belang zijn (de meest voorkomende praktijkbehoefte)

Er bestaat geen ingebouwde vlag voor het negeren van hoofdlettergebruik bij `includes()` en `indexOf()`.

Best Practice 2026: Hoofdletters en kleine letters gelijk maken
js
function containsIgnoreCase(text, term) {
  if (text == null || term == null) return false;
  return text.toLowerCase().includes(term.toLowerCase());
  // Of met ondersteuning voor regionale instellingen (aanbevolen voor productieomgevingen):
  // text.toLocaleLowerCase('en').includes(term.toLocaleLowerCase('en'));
}

console.log(containsIgnoreCase(phrase, "POWERFUL"));  // waar

Waarom toLowerCase() wint meestal

  • Sneller dan reguliere expressies bij letterlijke zoekopdrachten
  • Tijdelijke strings zijn goedkoop in moderne GC
  • Vermijdt de overhead van het compileren en ontsnappen van reguliere expressies

Waarschuwing met betrekking tot de landinstelling — Turks ("I".toLowerCase() → "ı") of andere talen kan verrassend zijn. Gebruik toLocaleLowerCase() met een expliciete locale wanneer internationalisering van belang is.

Alternatief met reguliere expressies (flexibeler, maar trager)
js
function containsIgnoreCaseRegex(text, term) {
  if (!term) return true;
  // Speciale tekens ontsnappen als de term door de gebruiker is ingevoerd
  const escaped = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  return new RegExp(escaped, 'i').test(text);
}

Of een korte omschrijving (alleen voor vertrouwde termen):

js
/2026/i.test(phrase);  // waar

Wanneer kies je voor reguliere expressies?

  • Woordgrenzen nodig (\bterm\b)
  • Afwisseling (kat|hond)
  • Lookarounds of andere patronen

Prestatietip: Reguliere expressie samenstellen een keer buiten de lussen/hot paths.

4. Andere methoden en wanneer je ze kunt gebruiken

  • String.prototype.search(regexp)
    Geeft de index van de eerste overeenkomst weer of -1. Tegenwoordig nog maar zelden gebruikt — omvat() of .test() zijn duidelijker.
  • String.prototype.match() / matchAll()
    Om overeenkomsten te vinden, niet alleen om te controleren of iets voorkomt.
  • startsWith() / endsWith() (ES2015)
    Gespecialiseerde controles — sneller voor voor- en achtervoegsels.
js
phrase.startsWith("Java");   // waar
phrase.endsWith("fast");     // waar

5. Prestaties van de motoren in 2026

Geschatte relatieve snelheden (V8/Node 22+, lange tekenreeks van ~10.000 tekens, letterlijke zoekopdracht):

WerkwijzeRelatieve snelheidBeste voorOpmerkingen
omvat() letterlijk1,0×Eenvoudig ja/neeDe beste keuze
indexOf()~1,0–1,02×Index of meerdere zoekresultaten nodigVan dezelfde familie als
toLowerCase() + includes()0,65–0,80×Letterlijke waarde waarbij hoofdletters en kleine letters niet worden onderscheidenTwee tijdelijke strings, maar snel
/literal/i.test()0,25–0,45×Hoofdlettergevoeligheid of grenzenOverhead van reguliere expressies
new RegExp(escaped, 'i').test()0,20–0,40×Dynamische/opgeschoonde invoerOntsnappingskosten + reguliere expressie

Belangrijkste conclusie: Gebruik omvat() voor letterlijke waarden. Normaliseer de hoofdlettergebruik voor `ignore-case`, tenzij reguliere-expressiefuncties nodig zijn. Reguliere expressies zijn 2 tot 5 keer trager, maar dit is acceptabel, tenzij in strakke lussen.

6. Randgevallen en valkuilen (van cruciaal belang in 2026)

  • includes("") → true (een lege deelstring komt overal voor)
  • null/undefined hooiberg/naald → TypeError
  • Surrogaatparen en emoji’s → correct verwerkt (UTF-16)
    js
    "Hallo 🌍 2026".includes("🌍"); // true
  • Negatief functie → wordt behandeld als 0
  • Zeer lange reeksen → zoekmachines maken gebruik van efficiënte algoritmen (gemiddeld O(n))
  • Gebruikersinvoer → nooit een reguliere expressie samenstellen op basis van onbewerkte gebruikersstrings zonder escape-tekens

7. Productieassistenten en beste praktijken

Null-veilige hulpprogramma (geschikt voor TypeScript):

ts
function contains(
  haystack: string | null | undefined,
  needle: string | null | undefined,
  options: { ignoreCase?: boolean; from?: number } = {}
): boolean {
  if (haystack == null || needle == null) return false;
  const { ignoreCase = false, from = 0 } = options;

  const h = ignoreCase ? haystack.toLowerCase() : haystack;
  const n = ignoreCase ? needle.toLowerCase() : needle;
  return h.includes(n, from);
}

// Usage
contains("JavaScript 2026", "script", { ignoreCase: true });  // true

Aanbevelingen voor 2026

  • Standaard instelling omvat() voor de duidelijkheid
  • Hoofdletters en kleine letters normaliseren in plaats van reguliere expressies te gebruiken voor het eenvoudig negeren van hoofdletters en kleine letters
  • Cache-regex-patronen
  • Meet daadwerkelijke werklasten (vermijd een obsessie voor microbenchmarks)
  • Gebruik bibliotheken (lodash _.includes, Fuse.js) alleen als je een fuzzy-zoekfunctie of geavanceerd zoeken nodig hebt

Conclusie

In 2026 blijft het controleren of een tekenreeks een deelreeks bevat in JavaScript een bedrieglijk eenvoudige bewerking, mogelijk gemaakt door sterk geoptimaliseerde API’s. String.prototype.includes() blijft in de meeste gevallen de voorkeursoptie — het biedt duidelijkheid, prestaties en een overzichtelijke weergave. Voor controles waarbij hoofdletters en kleine letters niet van belang zijn, is normaliseren met toLowerCase() (of, indien nodig, alternatieven die rekening houden met de locale) biedt een betrouwbare en efficiënte aanpak. Reguliere expressies moeten worden voorbehouden voor situaties waarin flexibiliteit op patroonniveau vereist is die verder gaat dan letterlijke overeenkomsten.

Veelvoorkomende patronen waar ontwikkelaars op vertrouwen:

  • Letterlijke booleaanse controle → str.includes(sub)
  • Met positie/index → str.indexOf(sub) >= 0
  • Hoofdletters en kleine letters negeren → str.toLowerCase().includes(sub.toLowerCase())
  • Complexe behoeften → In de cache opgeslagen RegExp.test()

Door de juiste methode te kiezen en rekening te houden met randgevallen — zoals lege waarden, null-invoer, de verwerking van Unicode en door gebruikers gegenereerde gegevens — zorg je voor code die zowel veerkrachtig als schaalbaar is.

Carmatec helpt organisaties bij het bouwen van hoogwaardige, op JavaScript gebaseerde applicaties, waarbij aandacht voor dergelijke fundamentele details rechtstreeks bijdraagt aan de betrouwbaarheid, snelheid en onderhoudbaarheid op grote schaal.