DEV Community

Kaziu
Kaziu

Posted on • Edited on

😇 "Javascript Closure" I think you can get what it is finally after reading this

💎 function in function

▼ in function can declare function in javascript

function outer(){
    function inner(){
        alert("poland");
    }
}
outer(); // unfortunately, nothing happens
Enter fullscreen mode Exit fullscreen mode

▼ we can write like this to execute inner function

function outer(){
    function inner(){
        alert("poland");
    }
    inner() // here !!!!!
}
outer() // "poland" !
Enter fullscreen mode Exit fullscreen mode

💎 Anonymous function

now executing order is

  1. execute outer()
  2. declare inner()
  3. execute inner()

it's troublesome isn't it? 😅
yeah we can execute alert("poland") shorter by anonymous function

(  function(){ alert("poland"); }  )(); // "poland"
Enter fullscreen mode Exit fullscreen mode

💎 function which return function

(in 2 min you can get what is closure finally)
▼ function can return function in Javascript

function outer(){
    var inner = function (){
        alert("poland");
    }
  return inner;
}

var func = outer();
func();// "poland"                 
Enter fullscreen mode Exit fullscreen mode

▼ transform it a little bit, define inner function normally

function outer(){
    function inner (){ //** here
        alert("poland");
    }
  return inner;
}

var func = outer();
func();// "poland"
Enter fullscreen mode Exit fullscreen mode

▼ now delete inner() and use anonymous function

function outer(){
    return function(){ //** here
        alert("poland");
    }
}

var func = outer();
func();// "poland"
Enter fullscreen mode Exit fullscreen mode

▼ then tranfrom a little bit, declare string "poland" before alert function

function outer(){
    return function(){
        var country = "poland"
        alert(country);
    }
}

var func = outer();
func();// "poland"
Enter fullscreen mode Exit fullscreen mode

▼ -- ⭐ IMPORTANT!! -- At last move var country to outside inner anonymous function

function outer(){
    var country = "poland"
    return function(){
        /** ⭐ ⭐ ⭐ ⭐ ⭐ ⭐ ⭐ ⭐
           looks like we can't see country
           because country is declared outside anonymous function. 
           But we can see it, this is typical closure 
        ⭐ ⭐ ⭐ ⭐ ⭐ ⭐ ⭐ ⭐ **/
        alert(country);
    }
}

var func = outer();
func();// "poland"
console.log(country) // ⭐ undefined because of scope
Enter fullscreen mode Exit fullscreen mode

▼ You can see easily with these eyes
Image description

💎 Real life example 1 (increment number)

there is typical question about closure

define function that return 1,2,3... each time you call it

it's not weird if you're asked about in in interview.

▼ If you write like this, result shows just 1 three times

function increment() {
  let num = 0 
  num = num + 1
}
increment()//1
increment()//1
increment()//1
Enter fullscreen mode Exit fullscreen mode

if we put let num = 0 in global variable

let num = 0

function increment() { 
  num = num + 1
}
increment()//1
increment()//2
increment()//3
Enter fullscreen mode Exit fullscreen mode

the answer is correct, but someone could change this num so easily by chance, it's dangerous

function incrementFactory() {
  let num = 0
  function increment() {
    num = num + 1
  }
  return increment
}

// factory is just increment function
const factory = incrementFactory()

// ⭐ here only "increment()" execute, so it doesn't have effect to "let num = 0"
factory()// 1
factory()// 2
factory()// 3

Enter fullscreen mode Exit fullscreen mode

as you can see in that code, "num" can't call outside outer function, so we can create like private variable by closure

(▼just note for myself in Japanese)
incrementFactoryは最初の1回定義されるだけなので、let num = 0 が毎回定義されてnumが0になることはないっす

💎 Real life example 2

Honestly example 1 is hard to define "real life" example, even though it's important to know this knowledge.
But now I'm gonna show you more real life example.

this is typical jquery code

// anonymous function
$('.button').click(function(){
  alert('Hi!');
});
Enter fullscreen mode Exit fullscreen mode

then I can make function that prevent clicking more than 2 times

$(function(){
    var isClicked = false;
    $('.button').click(function(){
        if (isClicked) {
            alert('you have already clicked once !!');
            return false;
        }
        isClicked = true;
    });
});
Enter fullscreen mode Exit fullscreen mode

Thank you for reading :)

ref:
https://qiita.com/takeharu/items/4975031faf6f7baf077a
http://dqn.sakusakutto.jp/2009/01/javascript.html

Top comments (1)

Collapse
 
peerreynders profile image
peerreynders
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" contents="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Real world event listener accessing its closure</title>
    <style>
     main {
       max-width: 11ch;
       display: flex;
       flex-direction: column;
       align-items: stretch;
     }
    </style>
    <script type="module">

     // `isClicked` is part of `clickListener`'s closure;
     let isClicked = false;

     const buttons = document.querySelectorAll('.button');
     buttons[0].addEventListener('click', clickListener);
     buttons[1].addEventListener('click', simpleListener, { once: true });

     // ---

     function clickListener(event) {
       // accessing/mutating `isClicked` in the "enclosing" closure
       if (!isClicked) {
         isClicked = true;
         event.target.textContent = 'Thank You!';
         return;
       }

       alert(`That's quite alright, thank you!`);
       event.preventDefault();
       event.stopPropagation();
     }

     function simpleListener({ target }) {
       target.textContent = 'Thank You!';
       target.disabled = true;
     }

    </script>
  </head>
  <body>
    <main>
      <button class="button">Click Me</button>
      <button class="button">Me Too!</button>
    </main>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode