Closures in Javascript
Tags: javascript
Published: 2023-08-30 06:54:37

Closures allow returned inner functions to capture variables defined in outer functions (light definition)

They are useful when used as private variables, or don't want to pollute global namespace.

Here are two examples of some of my previous posts :

[Counters](https://flems.io/#0=N4IgtglgJlA2CmIBcBWA7AOgBxYDQgGcBjAJwHtZZkBtABl1oF18AzCBAm0AOwEMxESEBgAWAFzBV8RMtzHw5yECAC+uHv0HCAVp2mz5ioQHpjAAnFiADgSSmA5hDEiArgCMMMsMd4RjfbjJoAB1uUwBBMzEIbgBPXDMCeCIXEngEgFUAJQAZAFoWEggFOHizF24IAEcXeESxIu57MwBJABEzewV4El4xMhIzFgGzACleADdeAGVSCCsxDFCEMTMAoKgAXgAKMU2AJgBGAEpNgD5SWIWyDC6xLN5uKDIwADVeWFqCbe54AHczBkYmIsOESL1YrtjscMGkoC4iPBtsixLh4KczmIANQ7eAAMk2ADYAMzHAA8xMJAH54Bh+tMGjF7NtKcckPAyYT9lTtvA8vtCTD6YymizBXSyBkrFYegBhXhJbZs+BnLlU4IgPIapAagD6GuOuA1BoA3KFQiwKkRorIzLKyBV5IMlWZgKEzGYVmYZI6zJszLR3UMrTbuGZXsUAS63WGPZ74KsXC5oH61o8Ni6zEGPV6oBAJqnnikBHJPGk+vAAKIIEtibYavMTA3ZsyNjAxX4kAASABUALI5VMAAxbHrJIkOZmgmzzBCssF4sTyABJgEnoCozqufXIVGTjBOzqOzGS3C4xP0w9Od06V2vk1BN7Kci1ZQBpfdni+yI+xj0jv941WMReBIO5C3zDAah6WJpngBBrQGbYhwAYlnedFzvddHyHY4s0Ar03DEMN-UbY8oNqEhYPg5J+hIZCUJvHosIfFRcPI2QiFgCAiAAa1TMwXXOKJQLudtuE7Ht4AAD1Wf0sSxG98LjMw0jEVIwzI2MVCDNSNPDSNBOOUIdO4UJqAwSywQhbYUGORgMGGEhK14IgRGRPDhKLFxawwNwyCgWIMF4aUSm2e1HR6JVoXNbgQHwJIENDTghEOJAABYAE5VHUEA+AEJRPAIPQQBkOQFDEJRVEYFQgA)
```js
// https://github.com/ai/nanoid
//A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
let nanoid=(t=21)=>crypto.getRandomValues(new Uint8Array(t)).reduce(((t,e)=>t+=(e&=63)<36?e.toString(36):e<62?(e-26).toString(36).toUpperCase():e>62?"-":"_"),"");

function Counter () {
  let count = 0
  function View () {
    let uuid = nanoid()  
    let div = document.createElement("div")
    div.innerHTML = `
      <h1 id=display-${uuid}>${count}</h1>
      <button id=counter-${uuid}>CLICK</button>
    `
    let target = div.querySelector(`#display-${uuid}`) 
    let btn = div
      .querySelector(`#counter-${uuid}`)
      .onclick =  () => target.innerText = ++count 
    return div
  }
  return View ()
}

[...Array(5)].forEach(() => document.body.append(Counter()))
``` 

Here is an updated version, thanks Eckehard

[RotatingImages](https://flems.io/#0=N4IgtglgJlA2CmIBcBWALAOgOwGYA0IAxgPYB2AzsQskVbAIYAO58UIBAZhAucgNqhS9MIiQgMACwAuYWO1qkp8RTQA6pAAQaAPBDABzDdAC8qkHvr74ZjWUKwIhANanzYS-H0AlYlPpTiACcMQN9-IIAKAEobKH96AFp6Un0EVwAGG3JAwlc4vyQLKwB6ACtGTwBuACN6FgA2NDxigE5S4rQAQU6ARQBlJwAtACkvfU6AIV7u6anOgBFigCYAdwBhAFFJnoB5eYAPAEkABXmvfo2Jw4ANADFzgE0ACVLDiSeJFcIX9PIAGQgPQAnn0AKoTACyfXSUE6XicADUegB1UgAOQgoNuCKkCMRAHFBm9YNVrlAsPoHgBpCYAFTAazRsDQ+xasHRAGp9NcVhN7oRrh9iPAdkCNhIdjh9rSvLA0QAODhPfaK5WqlVKjVqzXq3U6-Xaw1a41647FboTDaHTqHa2wToQq7jTY9DbzDY9J7FfbdegzNadFaXGYh0MzeZzNYTV344rynqdHZzTr6N2Bja3Cb6UHzQOgsM9Q65y0SCZXfY9LwQzHI277CZePoTJz0J4rCFOKn7FZQDalUEAVw2+IhxQ2TjR8wRG0IxTHk0IU1dS7Dq5mWxTZp9nV7y+mub3CbX3S8GzWh1pmY2YHurWICwdc0OXk6+y2xxWnQAXl-9vi+hy6R-AOxxQGi5BtsUfSMAAjs+hxoFAACMTg4DBUgtIwKzzA8UCnOkLRUmgEilDi9ReBIUBeFIABuTgbGg9TIsQ6SgukyLpGADxrCg6AclAhDytUeJgEsL4wfsDzDPsTjXFSxRAlSnTpKUUDEKCpQSAihxSAOyLXPMHAAqUbKMPoEgcDgjC3E4xRUoE8xPF+MFPLSOwPKQLTpM8HBgPsOydPAHA0UhMFeLStLEGiOxOPKNH0BC+iDNUgxfrR+ykKyVJYPMVJorSA5oksOZgGgfjFLcEJ-MQUA9FAOz6BCoKDE4wxYEhEiUmiNFfvAgyMIMUjHH8az7PQ1y0uQ+h+IBSxSBAhF9IMpCyC0OCgkVGxQKUA63DtTw4GAgQwcURIQFS+KdP81QDvM1QtPMYADuRjAoFA5BUjB95YIEtUTPUOAcgwaz0PiaIIoMk0QoMr5MBCYFrOx5CDGgsA9MMUg4IENF1g8LR-FAtIoOk9CHECwyHIEX49EsVJ+Usawcn8OATByDy3PU6S+JOGxovofwQp01QoPUCLIqCPSdfsCJgIcCoraU1QTKUxxIYMGzyvsWBUl4Kx9BCSxPFgoLqcinQwQ8Sy9WgXjytc8r0PAEtflgSzpOkgRUowwWZkhxzHH0MG3PihxOEsKZeGASEoLcKwcH0LTXMIrvXKQSFwk89B9PMNE4MMG1+S09C3PMOxoqetLDAOuBQMMLQcEsLE4PQFIwSsODwCs+fyqUTzDPKVK0oc8BPKCMFgQOPQ4CsxB1i0aBt0CXiMPswzFaUtywPM8p-A88pLByxRIcQpSkNUZPL4Q5ATPA+woIfKCMMzQIRfUMFolItIbIMEgPNchxPGOKQTmxQdjylBF+P4aJGCwGOPAW4QJGA-T+CgfQHAdjED6OLNEDxGDaTXjBHoRDaRISEuUL8oIESMHmPiJCYBJgDigF+fEpQvADnIOQCA+wIAQnnqQQgXg0BLBon0GigwoCkEOBsBE8xkaBFgIENAA56ATCBBIRgxAej7GrsMDgpQaJ+RgqCfEtJQRAhaMQJYSw0RgGRCgFgVJYDIgyi0TofRjgwWGCXC6+xCBYB6NUJwHA0BQX0IcJYKABzFCvgOfEo9ShAnlOPMACIJA4BaMcKQawaKSU6MiDkxxQRIQRCsa4PQw59FpNUJCTwkITBgXhamThSjIgRBAfE8w0QDgxkqUgX4HYh3QC0WkxReRolHIMAcfwlFQEYLBW41wRgMFBBADkEwHiEBoRwYg-g0Q7jWMjB4oy1j1B2CgUgxwgTFC-H0Ug9UljkA4Csv48AkIcikOnKQxNigTGGBJGCHAoA4B6AODgWBmSdHlLSNAByaK0j6C-egNFKCMHehKHsd10jHFpvjd0A4IDpDQLSeAX5SCwBwIQHAfwnLoXqLSJw5B6BeH2GAUpHBqh-E6KCfhThkQr1gH8fyX5fJPCgLcYYylpIQFuLcGCQJjh1GxlIdIhBbiQMOMBMFCJAgkI2MQCApQ-j0SWPUeYgQ+hgDAARdwYJOjytgDRNAxBDjIpuXMtE2LqgbBjqUB46QcC3GIGgFo+gei6W-Lyr8CINJAghMiIugwegQkYDRDgtwBxUjqX0LAJKvDkCWPsPotwmwPAeDRCA5ABzVCWIMGCnFYCDFgOQZgEMdiMHlDlLA+xrjEEIMiGi8BQhIRkqCNAaJ4APARHkiEXhWFOE6PiYZdSUBfi8GiQ4pABwDlIDsFoaw0BYARdyYYTxPIcjRNUfE5B2Jjr+EgtYyIlgIh2ECjk9AvwrAkD0LhETc72i-GgBEpR9iBHSDRKkQILboBwLdYY9AVhSA8lwgOEAvB-EGH0PoxByBeA5BsANEh6hxiQg8fQpy0RrCnQ8HANFqj7B6qUQD9BkQPAox06o9opBDRQOWjg1x9BIRGisJKWApBPBcv2MAHIkL6DWLbegW8o5rD+IcFYxRAhSTifsChMFrjZr6PiDYVILX40fQ8Ox8YqRSEOKUPoOBobzEOKzDYDxqgcnmD0Aa55QTDFKLmQITgOSdByRwUKPRLFCTs3hTolsAMqXIF+ayPQ35omuMiNRXgcB9HQ-iHo8wUCghouPZ9WAvxogxqhQWpQZwLUVO2vKRF0grGRH0LwQIljVCgOkDYETe3eD6BIQYFi7KMGKH8WkRi2RYEOOyjYwxCD6FZVIDgTgo6OtA+kL81a1gtGbNHCAQIxpAh2IOZEVJbi0i4-AKQUK-jUpoj0fQ+h5TSLAM3DgEwniwGGI0YguYeJjRgvm+ywwcBBAhN8W41pgqKCeGiWSC1PtZOC0segGDjj4nxDBJYKaT3mY+n0DYEAJDSP2FIQgnRSjkDZCsFU26QPXHxPQP4hAEqjt3jxib2bAhIWAciKuX57MdnSPUJwUA+gGVEksCAhxCAPHqKCTlaIoCJVBCgO+2kZaDDYSgJJKwaLyi5fAFADxDgoFfLcUg+JqlVopPMYUEH2UCIMPoZE9mgQQD0E8BC+xjiMCQuLa4WBiA7A4FejkyI0QSGxc4BKYBOUrRZoEYSaIYL4nSTRY2FsERIQhGiX1EIMKlHgYMFY9QvwcjQDsHoxwECMFpHGq1ME-j0GBF4A3nQwATEEhyQ4STYA7D+MiZOUzDigjHzgJSSwBzKCwOxYYwxijwCBIMIE5BCBEwVMUeYSFAjK9RVWLAEhbhLBgzBLAIEdgSD6M9fYax5TUf3vKeY6JHHwFKKj1vTxJ0w061gUPV+9ArIfuDw+IWA-OPQX4fa1wEwxwtIHstw7s16hANMoyEw2UDw8wO2FCOa1QxiHaWA6wNinKygoUgaGwF+VELy9QEgX4QIA4tIyIWAOUskecxASE9AHI2m8ALAPQH8ScaIpCaIb0HAj8X4SwOwX4awfQ6Mq+SwgcYAMcX6kCp+1Q1QYAhuOwTAae-SeU4oPEwyBWo8-MhwxAwwOyEwoITw1Q9QSESEhwPQuAH0hwEAWAjGawXE6cF6AmKwXg4cxA9QjAOAwkvUQsGwoCrwCInMaAiWhAMkykns0Cyi-qnQ9QcQX4AkqkEASwSE6hSwN8AeTwfQ9Q-gNkyIOwXggQ6a-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-i2M-+aADwMW-0nkoMTWHAtIaItwOwhICIaAwwh8A2xRMEyIjB+wEgww+IbtX6IjbmaIBJjAQITwCI8AdtEwMEOAWAKAwwEwSwTgaA5A8wKwhSk5DIhANETweStERxcQxQ+Ifw3o1wEAaNCIsBMERIsAhwOw7EXyj0EAwwv0XgmwE0ikgQcsZh1Q8ohwRGtycugQgwR84maAfmwcnsX4qi2mrurIQM8AhAbU4sVIEAIJTw8YhwGosAbSW2ruZIUy+IX4GwCxtI9GbE6hU8SLoIMJx+OLvgSpQI8w-gGwemHCFODwpQ3UxwWAUENESc8wtI20zqVJBU+zJjozCIEiWAMEYN9iHAj69ALQTwxA8U9AS8HL5AQIAR5AWwTw+IhAawUojAaAoGWM1w1QtI9A0ChwxStJ-M1tgQFNhANB44+ISw0MNELtg1Ryn46QDcEggQvuMEZY+IHAJR+g5AT9OwvzLQcqmc8AD6MscGnQexlLLQuAHIpAwdDwvgyIgwemoxgQwzMsWA4MHIVI8o8akchG+gNygipQWAQI5OUAaAVI1KpAOqEI8wfwME+GQITgRYUgoIOAZTGyJsxQxjXg9Q79fi+g+IUyATxwOMtwgQCIA4Ow+wUA3ItcZswwcNWNnDvULQJi5AEgMW+ggQ1wpaUAGU-k9Ans1wYAEgoMLzpQI9xAU6zY8orjXSn6+IEJEIhwsSwwL8QIHAEghAYAPJxwXgwwfTfwusMGSEklgEOA3UfwXaCIX4OwKwpQVI1Q8wwwFB0bihmBOy2MCIsotIHAoM4SD+rIrYTwoKpaYBLQAQMTpQwGp9vOJR3uROQwtwI0+wQIalgQB1IHaIXS9AT70MbxqJ1Q5o549FNEspawLY6MjABthwOAh0bRCw5itIMBx5hAKVKwdMWF8UKATwHIohME8ohACq7LXGOAFV8AOAzjTwM7KAuI7ZawQIoB3wKw9AG8h5EwwKEI+I876afw56fwPQgQ5AOAl4l6HI1i+wSE5atNrCWBlcTwlHgw3kgwNE6QTwEA9AVIQMLGVYaIxAEgEAEwSIcaTwQSf5Po9AVExwdliIXgwc292KjAUaMqPQloM4DX8wAksI1dnsTgxAl2hAGm1QiiTq5ZhqtwNE9QA43CXgzggoEgXM9ZYliHRUsAQWbyNEaknCLhdG9Lq2w3yIzZgLGG2IATUgPyPOMEtIupjJGq1L6aawVI3dUAhj7eA4gwSwwwyH2RMoxAK16QXgxw9Q8AaA8ojbSEi+wqKASE1wYPvMHIYADLOZwR20KsaIMjBq9LG+A4ITawiGaIcX+gNkYcYjUygUqXxsVI1Yto1tTgEgD6oEaAyIxQTw8dGikz-UhPpPZ19bz6+weBYAeeGwLWHIzKpC765onQHI5q4SQ98q1QAbTgltxi8w9QHA8wRc9QAnqKOwC31Etw8oUAYr7J1iqbHqIc1QjASwVSUgjAU8J6vNA4dsLQUIPEc7jsEo9QUUxAg0VapQgQIfYagwTwSww4LQ1QVUYA9Q5AOwsA9Q0L1QmGKwUz1K2mPQq+rwcpTw4LSws3LCYBZGQIhwgHvqTw8wqDsALbO77shawwRULQ0go8yoDnNyHsUgOGs5nCa0CUru2K9Ak7iFmEUgQbFOcQNE+IVI2KpQ0b7iOAtBZ8Sce5tw7XjZpQXGrhyI9Fgw9xyIIcfqTpO6Iv3glIaAQIKiWAXgiubctw3Qa01QpQoUCIVIoIOwxwHIOAoWGEfo+wF5O1mb4ZFP6b-KkE4D6CjIcIZoUpOFVuDGYJgl0dDhwBVAKY+gqycxmgCQjgxjk+INhHKi2Ach8QlhdICMBaCJtrgzfK9owDHhgVyexAEOC0AHDWg+gnQUOsUDJTvw08k7UEPoCrSzIbC7-BgPoGICAdQE12UoEDGOA9BHkUAB4OQHrYK9hBCIcrJYB2ZOAJgLId5KaQgDVx6g1QOxl+BYzT5q0omaCCxl-C0hpwklPoPsHqAmQPMAxAqMMDoh-AfqSlIxBhQqa0ZY4rJOYuVRMryg0aFg5nFf2I5eBjWyIOTDgDv70UqQ+kZYD0GMCuANAxQAAHzqAshmgHQHoEMAmAzARQeAEsBsB2AHAzgVwEUO8BhAAggQJYCEBqGRAYgIADQPkESDJBUg8ADIDYA0DZBcgsQeIIUHcAlBygVQWoA0CaCtB2gXQXoAMBGBjBJg0wboAmDmCLBVgmwboF0QmD7AoQGwO-l-B2G1g7+dwJbkf27zsxfE7MJbncH2CggLhrufkKbjWBPYSBVAfEL4m0hfwmmAwfUvul2gqgkO1pKQIzWmgAhr4zw4gFSHmD6BXGsceMMWhhB1gPYEGdIFIGErZBhKHsdEYEGxHoi0RKVHEdCBxEEo98UBSfECA9iM1yAUgKkGSNxFEiIM1I+SHL0tDWh4cqRR8IcGdAeg3QHoL0NuApydANwPQcEEsOPAzBowEIS4PoEIDWh9A-I7oC9m6ABhCwEYaNlGF6CZgjwEolMAsA9D9AHCxiJqBsCeBFVRghxOsElCKrqQuwPYDYOPipTH4NoEAJwDRBtB7QvATWOcFsCzBLhgwrocUWGCmCNRwi8YToE8FPB+inwB4QMUKJfAQANgPoVeOcA4DFA-QgYGMS6BnTw1lIr-QIPAEOAXEQ+GhXDLSAWo9B3uXZX5vKDABG86MTwFAMmi-BpMQ+hASEngnxAPAJiLEbjvg0TFG8wekoDYKQH-Zy4mBlKCAJcnlw8YNgK2RLMcB2xjtnIPQW4B9ECCkBigyIZEKIR+7HA-45IRGEmgHBSt4qKwd2K1RBQ7BUkEgGCDHBWBOIcAi6MAFIEMHgZBm5ACjPkjcids1gSEHCHkg4arFyAype+LcDPZdVQQaHD8PE3FSV53gVIVlmiGrG1iq0+wBsRCHqDbUc0f2a-CMjLSHpfwl5KES0CcDpB22WAEkttRpBAgecvUQsb5kCAljYaDUNSFuwZAApzcXbJ1KIhQBZw70D0KPuQH2DDVx4DRKiEFWTwVUn4jE+UKWKeBVjEyYAaoGsHWpkCHOOwQICsETjk4tIaAJ4ECC-B5RjgEAMtLRFnD4g0AoIUZB1X0C009UX4QIADGuASBXYoaRCchLrFoTGx0PCyhsCJjmwBIA1KcfUBnErYgQpAM8P7jolFiZJpY8sZWKQmKTPJ6EleAFInHBTQpTgcKZFKQjRSGJTEssSgQSkeTUJKUn0OPHSlucB8hwc8KpSkw0QE2NEayX8FnGG5HkhuIEMPluDx8GppAK3G0FuB7kHgyQfMPKEkqjYHCaIL8IcFgC9RqMwFUoDgDWBQA9M7yDkPKi7ZgBLwPZXYBv2GD61jgCIBXheA07HYuICxQKOkBJD4N6AxAcFFgCMbzBXWKAeRN2yQQWRNBEIarByFBD1BCAbIZsrAAHBI0EMtbcwj9ghAcgPxxrONLPHLY4BYAsAa4MdBuxLB9AKAI4khE7IbBbJMERYvtRghbthQHNfQCsASb1hEe1wDhLQyBAikoKmiJCOQDPFAIV0uvWADCRvyfgc2VMqQBRKulrQ5SPmZgBxln6xgcZhAYLsfA4LSgdetcJqBzU6B0liAJbQ4MwOuA4yfprEBDEn2raEBIJUANpC3n9QG5U4F6fEFDJgjHAZ0lwPYXCB5GRjbZp4V0A7JfC0gPIPQNpE-Udighvg7BToMRy-CdBigwteUEhHswBFjghuPqGiFOISB4wOAmCKpDMTWgEwnY0iBAAUaUh8Q8oeAE4GFQQgEqtOIEGABaAilie46LADREID7QUA-VeoKbx6BIR9Ga+UZrOSYDUouEzMKpk+wmDSdnyofbKJOS-Bkhy2CE0DhSGGBYog6aAa4BXRojHkisBtDgAiFOLtheJddfWoh0UBQhrqSwbaH0A4YtIHgMEGvukH2BBUc4jpRuWgCKpu5qgg01iJzA2BJhqMU0mqDSSUnIgjifQQgPbxJRUhZkmsatFaHXyMEsACIJKGAT5S1gJm1ELbI0FXxYALE11JWjICAJtpMInDa4OglIDVYqQEgZEHmkYDDAeg-YRaoQGZmvhHEKxW1uQCgDb4ByPQXWiiHSDgoM6TgeaPKCLT1hm8LQcuL6XmBfgBwtETiIECdJm8x4oIOivPTNgVtAwIECAIMC6TUQIQDwT5tLVIAcgf4k5IUnQT1nVA0ABEYgKeFsoaFUOEIFyENCOLsRm43tL1qlj6CWRfwIZb+BwE6DEBrgecalJrBqmt4ZcYSGXLVM6D+KXCNUlwsEq5GhK1gHAMHk4ArG7NaggMJlolhognwxoyKeeWrQ4Bewp47UUjF+DADW5mqnSJOhNikCNV-aumIxBcX0CnN2CqCa4G0GngKgA4UBQYKCFoEIhlmRMCgFQA+qAg3G-YUkvgxOyoNO4Q8ZlhsGGSB8WgOwQ4M5FDJIRrwTEKKlgDAIb8sS2MQYAeyxRnxMIKAUUOZ1W5+onAsnFpAJS-CZkpAEIHEM2xQLSsHgBcg6EjK3qIxhEZOU0s+I-hlAEI1wDCCgGtzVwvAewNCf-B+4VU+gOqGiI8teilAthdYMFNcFgDjFskDMTlADGEKDT9mKxDJIQV7g996WnsFoD5W-hgAJUxwN0HeQIlbTqgfhZaBzwmCfBX6AKh4B+WsgyEvA4JJlGgBCWBLwlvKsJapQFXnhSA6QAMJ3lpCStDgSii2KgWpiRzOgv81quTTHiDB4A8oDkBIEBrPl8q6hMtKZygASAwAVIdGXRTYaghrgOAkCLGGOAJJ9AUAT-jgHmBih9gisECFSB2DBxVS+GfGH0BsKHp5Q+gD+OkARAnyskMcYoNcGuDMIhJlMq+hwFgBTLSQCIYWBDTJzNwBs00NAJpWIDWR75dQvvMDJ6BgBSefwX6Bx2tDlKtYHLJYLABaC1wwUHVJgJmnOhcRglrFQWkSnOqlBRmX4TkplwkAKVvgKpK6QXwNYchQaLMcqgX0SXkoaIbJRWAXKugdQrWY4EXlpTe7ozUwHAeAI7DRD0BSMTgCAC3U8qAlyAZIeUFulGoWQvwsAXSIBUJQVpAoxQRGqCCWBgBCAeqRVthlZikAOAByKkAWiZkV9Ly5AbSBwyBDjMq4Yg8uCsBzKDAcIrUuhFpLQAU5ohZje1VwCP5MQMwOwXEIwETaKBt4DLY1pO0o6DrhMpKZVGOHWRSCKgyM+GN3TtYCkZAsoXME9n0ClBHs8oWCMShr5jwsAzwtYCrSsJMRVWKwNwmsEbYZygGFiyFSmDBonBhw8AEhcKv5WRK+VQqrkTEobL1A88YAaydRFk7KYMS4MedfbULEt1aQ+WclF4GuCaQ-CutFqYk1nwfj-ZREJ4FGHSCpZA5bDE9LABZQhkoqcy2UseI4AcgKGnjZsYllKBkqWMHG2zJtmox-BVGC4qDnvPIDuAZMyuOBNcCBBoAQmliFySiQ3J7yqE9begA3luA3zIU8wQGONXxCBBcuSkoDKFghBfh+6c0eYvZg6ULdyAnQP4DkQHCtYtJwwLSMxC0rDAKVB9ZpNcBXloAcAZKLMm1lgBRUgktsY-M5PkTAiLY-62TOgCkI7B2ggwQYBzHeCtRyAtwX+NBFBDGSLYgwFAOctUFXokWBYo3jRBnA7DyAJyLKSfiFK3CMSM1FJLAG0YSaIMQ7CANZMFwVpbgHIeUNSPWp1AWg4RCQKTxapw6maVZeAB2SALXVrOeCZrMlHkkoVZQzKhJGAF8DkAsAfyYaTGVZx-sHg8cCTf5A4UWwqZnTOGlCUrkHs6i41cnH+TdgDgHIAqFiJiw0xfhOkI1GCFNUMmokrZKjKkHsJtkvgnZSuy0Crp5HvFkQyiG4kRh4aMq34U1DpSGgNlYB4q8AO4OZlID6QuFYNNwisFVkIkJc9QfLbIHgASBYm3VC2HwLNjgxaQX4ewrmBaDByoCQai1ux1PKMBOoPQFYN0nK7Kp5QkhJUj92GCaC6wHifASzVszB5XWTbaAe7WIAQgPFEkdrvgwhCQAEMxwbYR9S-Co74AEIJ4NTgPVcozYZtDCugDZp2Z5gEgKkKUkYJM4PoOxdIJiHt6BAsWp4YBDBEBCARSQ6aJCV4HmCVNB09g0gJM15kwZhghSj9nYx6w0RmoG+AJC8xPnCEusly5Up9ymDAiFOdkfuIwA-yZ04MklDxDIAc4so-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-sPNqCEoDDBuI2+J0hXjSiDK-g3WDJB6o2CBBmwEC6oE9iNgpUiy-NPTJCo4A4WUAlRCVpXm-AjUqQmCGJk8E9AShbJ0PKkMICxzoQhJfAxpeYUpIFpGtJJ9wPrnWq22VgTgBck2w+RIQyKls86CukLx8lhGC6DcccFTYyZpdEIKZp6tKAQ9K6mMEiaCHsa2IwA3+ZC7WItZuwpWqe1S2hI1TVAyJUAXu5XiUBAR6gLuxOBsBbyYsLdsCRyipXr30sjM0xdY7QTQmGL4q36egMp3Us3i31bbToNfmXi9phFMCHYEhFppXTG06QYYMzQbGr6V6tCUauzRVKghRCssIZqeD+WDAjjqbAcFdA3Qu1VuahfYOkDDOzyZEaSbWNiEDmxQHIxif-Zm3JwwYLdKuWzplj9wIMIQrsHG9takAcgOOlpqAQJR2DwAnSwhR2Bv0GAlqJCJJFWuD0EWuipMlGQIH7jWCwRCoRkTggxXSRB45oEIBTGHjkYjFO2lKQYBAEqQYyfMXVKHJc1YOCqJgb2cKMIrsFMxKYaIMbA+SeALVlS5SumrwcW1hoBgu91DpykQrKRugXQekCzmTzF0dgF0W0Nst72QYk0wkgYovkEWt90GtdUvKzZVz5wkONEleve0qQtwbE2a7VFbigBPBSmN8eACpTugQJZ+IiJ4OTzchLAbgqGWACfmbIHxTl6lgvuUEVzNI1g97bs4OfytxRSsZcdLBCH9Rmn1EUemdH0EBbAIuMgUJCHNCFifcJUNEbxysX2D85izb0Qy2MeG0qbYAu92Rh8h2JV5JyZTfUk3I4QJgpAfQJCDPBognkDKp8NWsQwGp4Ivw5oHYCo1HZYVj576t0YqFjpQBFFjQECv7aZqiq-uyTfxJSnqCfho2+IBHlIAk0AJYwRkNQubMsCQj2UsnCmogTQCL6GQWCYIr-w0wPIwztwSHkJKBim9aQMZtxoFgqLPMFE9eDfPQH-oYt65fAhIYcRWANQEsGrd9fyQhCURfUyIIUm+awzTkdUFYtYCps8r9wgQ6hRpUc9q3NssSSVQIGNsnx+QWAsB7REUV9tANWQ4sJGmAnWpwosEUe4Vvngd4-TIk+ROFJeXtXdBK29YNAI1QQRa9BQOMI6FAVhCfxps4RnAKKhWAjjoEHqkxilpigPECFIFcgNlmjZBWGOEINavolpDnQV8KkhEPcXQa0hlSWdR+CKVg6YwLKKwP0-ME6Tf6pi+UDgF+Cr3bLaMemBwPBmfCT1pDVciLkq8j5d5N8t6-sIzKkJqLakQusNM1CkD85v2MEEMozU7xvRYOaESQqLHtDo1t+f44ZOng4BM1i5QsahoSkWSGwJEN8Ttr63KpYA+Q+IfmDgnmB2JpmSnElBwGEUHZEEI2De3PzghHxhCLQW+9SNaSrYI8xQfoBklkT4gszOQaNCtmKYowx9e+hQVgG6lWygQ1WTLcMEYB7D8Fjsh4+rqeNq7bZxKB7FIF3YxyhJMgein2UOBjskQMqaJAJwuxUgWgrIT+ksBJQgGBwPaysLLHFO9MgqjMel04Akg0Qc8s5IvTsB3Sdw5tTc9pMcEo723axITPRBMDlt1cYSw3R6HFTVZ3lgMSyjtCL0aDocg1MmckElHHxK4W4ncXnFF7dwCl5g8AZEFIFgASbYA8xcIgPnMxogWggwSujhWshPSKdQdSPCkwci5qEEvQFWgRCuasAzcpcnAOXwhJHqNNnB4Vc3xfC-xASZ4KK6YkLD85y47Dh4Kt7WDreJYhwLb8t929LL9vEADb0d6W87e9vB3zb9d5W9ne7vZoU6DYAyHqAtA6gbQAZaMBQBXAIgDhB4DMCZCchX3y00sBB-yAWACAQgPNDIC8AxA8oJAGgBAAABfPAIIGECiBxAVOeQCQEUDKApANAOcBoAUzAkVgGgOuuwggApANAn6bgPAA0ChA-ASgdQAx-4Rw-NA5ABAOWQiBJ2NAxgDQOkCiAaBgAH3rQEz+uxC7NApATuBoG9piCK08ACIPmMoAOpGfxgdIb0OuzruRAopKQCr54JUAB0eADQEnaiBRBKg6gVH9kJJ-5jdI648gKT80DEAX+4LKQBoHx9+AafNPwwAZ8Z-2BsMQuxn8kCgAaB-fkvxcsoFQZh+ihbP7dLD5haaBmf-gAscMMZ8RBoAIvsXzkIQAe+OhCAAX0L6t+5-rslP-MfFBSCF-BfmQUvx77yFF+1I7jEQIoAwBWA-rCAFv5HXL5QBM-UAS3+L7qDhTCAGgdn4n7IAaAAA+in6UAV9DA0QUX+L60D0-C-EQAv4z+0Dl-4AlfzoRoA5AaAvI2fpfxL-X97-BffDkvxL5P+ed2avQnn4wAiDC-j-WgPIRgGpGCl4AGAY68kEeRBAwARfgAAMZ-ZXwAASYAHX9UfKAE8AogAAI0BL-CXxt8chLQDz9JfakSL9T-AAFID-dIHgCtAEnxp8xuQukJ8jAJ31IBfAUn1aEIActEoBAgWwA4BsA4-xJ8VgEP22h2ED3wj8Z-JP2P8+iDQEN80ArX2F9F-JAIl8V-DP1V8PfAQKP9hAq-1QCPfBIHP9n-a-3oBb-bn3gBefJ-2kCJfV-3f8EAL-0CAf-bZEYlAA4AIiAwAhICSAq-eAEgDoA2ANwCEA4-0QCr-V-zaEWAKQAwBT-QX3X9j-BTm38PA5306Fj-bRnBZ22dP3IBogcX0cDJfB300BgAJn0aFAgJACn9gAuf1N8ihIYUMBUfOAOt9bfYoDp8A-Ja2cAjAegLJ8jAUINJ98xIwBl8xBBTEp9sMdmi4C-1BP059PfAoJCCPAJ3wX8c-ZALL8FMCAH0BZfMP0F8+AKoR8AWfIIFSD0-aoTGC6hAAF0QgVgAHBUGCIA0Bj-Mf2aCggwoLX9CAQgDwA8hZnykCZAqIOl8tATPwMBmfDACKEMAFwOux3AywI0AsApA3SABfFISF8RfAADI3g0n22Cl-RwNN9jrGfAH9NAHgLX8HAfoNYBs-FYKQCAfRlCsALgvqUHRiUMnCL8IgMwGEtygxnyVdiAT32EUeCDQE7xB0RwGSB5fW-wS9EZDQGJRRiDOUCAzAGIE0BHA5UxYAhAq-2hCPAOENl8dUW+A99BfMwB5C6Q7INIB4-DnyT8zfZQM0BOg8XyYDGfK9gHRw-LEKgD7AM9gxCJAbDEZ94oJrXoAOMEPyd9UgV3wUxyACUNyCAgUny4x6AbRlsB+EcoScANAbf0J99QnIUiY7kYgBWALgyYNGDwgWgMF9kg9PxRC3AIHxABAQ5fxp81IZ0JGD4gpYCL8vQjwB9CihEoX9D4AjYLaCrADoNpCtAfHzV9P-YEn0AIgEMmLxYfDAEmI18U4I8Apg90It9L-fkPUB3AGn3CCBQ2sI+8ofZU3d8k-BHxABdcJAHqAEgdICQB0gNHwx8QAIQBEAaADACvheAAgC99CfGgDR8Zg1HyAA)

```js
// allow pausing while rotate
function sleep(ms = 0) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// returns an object containing the closure and the refrenced image
function rotateImage (id) {
  let angle = 0;
  let prevangle = 0
  let img = document.getElementById(id);
  async function _rotateImg () {
    while (angle < prevangle + 90) {
      angle += 19;
      await sleep(0)
      img.style.transform = `rotate(${angle}deg)` ;
    }
    let rest = angle % 90;
    // increment is not a divisor of 90
    // we adjust the rotation
    if (rest > 0) {
      while (rest > 0) {
         rest -= 1
        await sleep(0)
        img.style.transform = `rotate(${--angle}deg)` ;
      }
    }
    img.dataset.angle = angle
    prevangle = angle
    checkImages()
  }
  return { rotator: _rotateImg, image:img } ;
}

// we check if all images are in nomal position
function checkImages () {
  let aligned = [imagegRotator, imagegRotator2].reduce( 
    function check (acc,imgrot) {
      return  (imgrot.image.dataset.angle % 360 === 0) && acc
   }
 , true);
 if (aligned) { 
   message.innerText = ("We are two cutes American Pit Bull Terrier")
 }
 else {
    message.innerText = ""
 }
}

function main () {
  // we have to declare those variable as globals
  // to attach onclick events
  window.imagegRotator = rotateImage("image");
  window.imagegRotator2 = rotateImage("image2");
  checkImages ()
  console.log(Object.keys(imagegRotator));
 
}

main()
```