De flesta språk utvärderar inte varje del av ett booleskt uttryck — de stannar så snart slutresultatet är garanterat. Detta beteende kallas kortslutningsutvärdering, och det är en av de mest användbara (och mest missförstådda) funktionerna i boolesk logik i kod.

Hur AND kortsluter

Med &&, om vänster sida är false, kan hela uttrycket aldrig bli true — så höger sida utvärderas aldrig.

function expensiveCheck() {
  console.log("I ran!");
  return true;
}

if (false && expensiveCheck()) {
  // ...
}
// "I ran!" skrivs aldrig ut — expensiveCheck() hoppades över helt och hållet

Hur OR kortsluter

Med ||, om vänster sida är true, är hela uttrycket redan garanterat att bli true, så höger sida hoppas över.

if (true || expensiveCheck()) {
  // ...
}
// expensiveCheck() körs inte här heller

Varför det spelar roll: säkerhet

Den vanligaste praktiska användningen av kortslutning är att skydda mot fel innan de inträffar:

if (user && user.profile && user.profile.email) {
  sendEmail(user.profile.email);
}

Om user är null stoppas uttrycket omedelbart — user.profile kommer aldrig att kommas åt, vilket innebär att du undviker en krasch av typen "cannot read property of null". Detta mönster (som ibland ersätts av optional chaining som user?.profile?.email i moderna språk) förlitar sig helt på kortslutningsbeteende.

Varför det spelar roll: prestanda

Ordna dina villkor så att den billigaste kontrollen, som mest sannolikt misslyckas, kommer först:

// Bättre: billig kontroll först
if (cache.has(key) && cache.get(key).isValid()) { ... }

// Sämre: dyr kontroll först, även om det ofta är onödigt
if (cache.get(key).isValid() && cache.has(key)) { ... }

I det andra exemplet kan du anropa .get() och .isValid() på något som inte ens existerar ännu — bortkastat arbete, eller värre, en krasch.

En vanlig fallgrop

Kortslutning innebär att sidoeffekter på högersidan kanske aldrig körs. Detta är en vanlig källa till buggar när utvecklare förlitar sig på funktionsanrop med sidoeffekter inuti ett booleskt uttryck:

// Farligt: incrementCounter() körs bara om isEnabled är true
if (isEnabled && incrementCounter()) {
  doSomething();
}

Om du behöver att en sidoeffekt ska köras varje gång, göm den inte inuti ett kortslutet villkor — anropa den explicit på sin egen rad först.

Tumregel: ordning spelar roll. Placera de billigaste och mest sannolikt misslyckade villkoren först i en AND-kedja, och de mest sannolikt lyckade villkoren först i en OR-kedja.