Link Search Menu Expand Document (external link)

JS 1.7 Lexical scope

Table of contents

  • TOC

Vad är lexical scope?

Lexical scope beskriver vilken access child/nästade funktioner har till variabler deklarerade i dess parent/yttre funktion.

Exempel

const init = () => {
  let number = 2; // local variable created by init()
  const childFunction = () => {
    // the inner function, a closure
    console.log((number += 1)); // use variable declared in parent function
  };
  childFunction();
};

init();

Lexical scope innebär alltså att en funktion har tillgång till sin förälders scope (och variablerna som är deklarerade där). Kallas ibland för ‘static scopig’. Innebär att variabel bara kan bli kallad/refererad från det kodblock/closure där den definieras. En sån variabel kallas ‘private’.

Motsatsen till lexical scope är ‘dynamic scoping’, där variabler kan kallas/refereras även utanför det closure/kodblock där de deklareras. De variablerna kallas för ‘public’.

Mer exempel

I funktionen doSomething så kommer vi åt variabeln x, men utanför funktionen så kommer vi inte åt variabeln y.

I funktionen doSomeMore kommer vi åt alla variabeler, men utanför den funktion så kommer vi inte åt variabeln z.

const x = 1;

function doSomething() {
  const y = 2;

  function doSomeMore() {
    const z = 3;

    console.log(x); // 1
    console.log(y); // 2
    console.log(z); // 3
  }

  console.log(x); // 1
  console.log(y); // 2
  console.log(z); // undefined
}

console.log(x); // 1
console.log(y); // undefined
console.log(z); // undefined

Closure

Ett closure är när en funktion har tillgång till sin förälders scope, även efter att förälder-funktionen har ‘stängts’ (closed).

Exempel

const init = () => {
  let number = 2;
  console.log(number);
  const childFunction = () => {
    console.log((number += 1));
  };
  return childFunction;
};

const result = init();
result();

init() returnerar nu childFunction istället för att kalla på den. Detta innebär att när variabeln result sätts till init() så printas den första console-loggen, men inte den andra (den som är inuti childFunction()). childFunction() kallas allstå aldrig, istället returneras den och finns nu i result. Detta innebär alltså att den nästade funktionens förälder-funktion stängdes innan den nästade funktionen kallats. Om vi console-loggar result nu så får vi ut funktionen childFunction():

ƒ childFunction()
name: "childFunction"
__proto__: Function

Eftersom funktionen i result är ett child till init(), så har den access till variabeln i init() (number) även efter att den stängts. Vi har alltså skapat ett closure, som låter oss öka värdet på number varje gång vi kallar på result().

result(); // 3
result(); // 4
result(); // 5