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ใฏๆœ€ๅˆใฎ๏ผ‘ๅ›žๅฎš็พฉใ•ใ‚Œใ‚‹ใ ใ‘ใชใฎใงใ€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