JavaScript-funktionsstängningar


Innehållsförteckning

    Visa innehållsförteckning


JavaScript-variabler kan tillhöra lokala eller global omfattning.

Globala variabler kan göras lokala (privata) med stängningar.


Globala variabler

En funktion kan komma åt alla variabler som definieras inuti funktionen, så här:

Exempel

function myFunction() {
    let a = 4;
    return a * a;
}

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined inside the function:</p>

<p id="demo"></p>

<script>
myFunction();

function myFunction() {
  let a = 4;
  document.getElementById("demo").innerHTML = a * a;
}
</script>

</body>
</html>

Men en funktion kan också komma åt variabler definierade utanför funktionen, så här:

Exempel

let a = 4;
function myFunction() {
    return a * a;
}

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined outside the function:</p>

<p id="demo"></p>

<script>
let a = 4;
myFunction();

function myFunction() {
  document.getElementById("demo").innerHTML = a * a;
} 
</script>

</body>
</html>

I det sista exemplet är a en global variabel.

På en webbsida hör globala variabler till sidan.

Globala variabler kan användas (och ändras) av alla andra skript på sidan.

I det första exemplet är a en lokal variabel.

En lokal variabel kan endast användas i funktionen där den är definierad. Det är dold från andra funktioner och annan skriptkod.

Global och lokala variabler med samma namn är olika variabler. Att modifiera det ena ändrar inte det andra.

Notera

Variabler skapade utan ett deklarationsnyckelord (var, let, eller const) är alltid globala, även om de skapas i en funktion.

Exempel

function myFunction() {
  a = 4;
}

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>Variables created without a declaration keyword (var, let, or const) are always global,
even if they are created inside a function.:</p>

<p id="demo"></p>

<script>
myFunction();
document.getElementById("demo").innerHTML = a * a;

function myFunction() {
  a = 4;
} 
</script>

</body>
</html>


Variabel livslängd

Globala variabler lever tills sidan kasseras, som när du navigerar till en annan sida eller stäng fönstret.

Lokal variabler har kort livslängd. De skapas när funktionen är anropas och raderas när funktionen är klar.


Ett motdilemma

Anta att du vill använda en variabel för att räkna något, och du vill ha detta räknaren ska vara tillgänglig för alla funktioner.

Du kan använda en global variabel och en funktion för att öka räknaren:

Exempel

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  counter += 1;
}
// Call add() 3 times
add();
add();
add();
// The counter should now be 3

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a global variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

Det finns ett problem med lösningen ovan: Vilken kod som helst på sidan kan ändra räknaren, utan anropar add().

Räknaren bör vara lokal för funktionen add() för att förhindra att annan kod ändras Det:

Exempel

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 0

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  let counter = 0; 
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The result is not 3 because you mix up the globaland local counter
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

Det fungerade inte eftersom vi visar den globala räknaren istället för den lokala disken.

Vi kan ta bort den globala räknaren och komma åt den lokala räknaren genom att låta funktion returnera det:

Exempel

 // Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
  return counter;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 1.

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>
<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
// Function to increment counter
function add() {
  let counter = 0;
  counter += 1;
  return counter;
}
// Trying to increment the counter
function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

Det fungerade inte eftersom vi nollställde den lokala räknaren varje gång vi ringer fungera.

En inre JavaScript-funktion kan lösa detta.


JavaScript kapslade funktioner

Alla funktioner har tillgång till den globala räckvidden.

Faktum är att i JavaScript har alla funktioner tillgång till omfattningen "ovanför" dem.

JavaScript stöder kapslade funktioner. Kapslade funktioner har tillgång till räckvidd "över" dem.

I det här exemplet har den inre funktionen plus() åtkomst till variabeln counter i den överordnade funktionen:

Exempel

function add() {
    let counter = 0;
    function plus() {counter += 1;}
  plus();   
 
  return counter; 
}

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo">0</p>

<script>
document.getElementById("demo").innerHTML = add();
function add() {
  let counter = 0;
  function plus() {counter += 1;}
  plus();  
  return counter; 
}
</script>

</body>
</html>

Detta kunde ha löst motdilemmat om vi kunde nå plus() fungera utifrån.

Vi måste också hitta ett sätt att köra counter=0 endast en gång.

Vi behöver en stängning.


JavaScript-stängningar

Kommer du ihåg självanropande funktioner? Vad gör den här funktionen?

Exempel

const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter}
})();
add();
add();
add();

// the counter is now 3

Prova själv →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter;}
})();

function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

Exempel förklarat

Variabeln add tilldelas returvärdet för en självanropande fungera.

Den självanropande funktionen körs bara en gång. Den ställer räknaren på noll (0), och returnerar ett funktionsuttryck.

På så sätt blir add en funktion. Den "underbara" delen är att den kan komma åt räknaren i moderomfattningen.

Detta kallas en JavaScript-stängning. Det gör det möjligt för att en funktion ska ha "privata"-variabler.

Räknaren är skyddad av omfattningen av den anonyma funktionen, och kan endast ändras med hjälp av add-funktionen.

En stängning är en funktion som har tillgång till det överordnade omfattningen, även efter det att den överordnade funktionen har stängts.