Skip to content

Latest commit

ย 

History

History
331 lines (239 loc) ยท 12.7 KB

2019-07-01-Udemy_JS_Closures.md

File metadata and controls

331 lines (239 loc) ยท 12.7 KB

2019๋…„ 7์›” 1์ผ

Closures


  • ํด๋กœ์ €(closures)๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ผ๊ธ‰ ํ•จ์ˆ˜์™€ lexical scope๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ํŠน์„ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

Closures allow a function to access variables from an enclosing scope or environment even after it leaves the scope which it was declared

function a() {
    const grandFather = 'grandFather';
    return function b() {
        const father = 'father';
        return function c() {
            const son = 'son';
            return `${grandFather} > ${father} > ${son}`
        }
    }
}

console.log(a()()()); // grandFather > father > son
  • ์œ„ ์˜ˆ์ œ์—์„œ ํ•จ์ˆ˜ a,b๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ HOF(Higher Order Function)์ด๊ณ  c๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜์ด๋‹ค.

  • ํ•จ์ˆ˜ a์— ์˜ํ•ด ํ•จ์ˆ˜ c๊ฐ€ ์‹คํ–‰๋˜์—ˆ์„ ๋•Œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ณด์ž

  • ํ•จ์ˆ˜ c์˜ ์ง€์—ญ ๋ณ€์ˆ˜์ธ son ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•จ์ˆ˜ a,b์˜ ์ง€์—ญ ๋ณ€์ˆ˜์ธ grandFather ์™€ father ๋„ ์ถœ๋ ฅ๋˜๊ณ  ์žˆ๋‹ค.

  • ์ผ๋ฐ˜์ ์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด call stack์— ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution context)๊ฐ€ ์Œ“์ด๊ณ  ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution context)๋Š” ์‚ฌ๋ผ์ง„๋‹ค. ์ด ๋•Œ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution context) ์•ˆ์— ์žˆ๋Š” ๋ณ€์ˆ˜ ์œ ํšจ๋ฒ”์œ„(variable environment)๋„ ๊ฐ™์ด ์‚ฌ๋ผ์ง„๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜์—๋Š” ์ ‘๊ทผ ํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.

  • ํ•˜์ง€๋งŒ ์œ„์˜ ๊ฒฝ์šฐ๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค.

  • ๊ทธ ์ด์œ ๋Š” ๋ฐ”๋กœ ํด๋กœ์ €(closures) ๋•Œ๋ฌธ์ด๋‹ค.

  • ์•„๋ž˜ ๊ทธ๋ฆผ์„ ๋ณด์ž

  • a ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰ ๋˜๋ฉด call stack์— ์œ„์™€ ๊ฐ™์ด a ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์Œ“์ธ๋‹ค. aํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ์•ˆ์—๋Š” variable environment๊ฐ€ ์žˆ๊ณ  ๊ทธ ์•ˆ์— grandpa๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค.

  • ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด a ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋Š” call stack์—์„œ ์‚ฌ๋ผ์ง€๊ณ  grandpa๋Š” ํด๋กœ์ €(closures)๋ผ๋Š” ๋ฐ•์Šค ์•ˆ์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค. ํด๋กœ์ €๋Š” ๋ฉ”๋ชจ๋ฆฌ ํž™(memory heap)์— ์žˆ๋Š” ํŠน๋ณ„ํ•œ ๊ณต๊ฐ„์ด๋‹ค.
  • ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ(garbage collector)๋Š” ํด๋กœ์ €(closures)๋ฅผ ํŠน๋ณ„ํ•œ ๊ณต๊ฐ„์œผ๋กœ ์—ฌ๊ธฐ๊ณ  ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • b ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ call stack์— ์Œ“์ด๊ณ 
  • variable environment ์•ˆ์— father๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

  • b ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ๋ณ€์ˆ˜ father๋Š” ํด๋กœ์ €(closures)์— ์ €์žฅ๋œ๋‹ค.

  • c ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ call stack์— ์Œ“์ธ๋‹ค.

  • c ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด๊ฐ’์œผ๋กœ ๋ณ€์ˆ˜ son, grnadpa,father ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

  • son ์€ c ํ•จ์ˆ˜์˜ variable environment ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ํ•˜์ง€๋งŒ grnadpa,father ๋Š” c ํ•จ์ˆ˜์˜ variable environment์— ์—†๊ธฐ ๋•Œ๋ฌธ์— scope chain์„ ํ†ตํ•ด ์ ‘๊ทผ์„ ์‹œ๋„ํ•œ๋‹ค.

  • ์ด ๋•Œ ์ „์—ญ ๋ณ€์ˆ˜ ํ™˜๊ฒฝ(global environment)๊ฐ€ ์•„๋‹Œ ํด๋กœ์ €(closures)์— grnadpa,father ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

  • ํด๋กœ์ €๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด์˜ ํŠน์ง•์ด๋‹ค.

    • ํด๋กœ์ €๋ฅผ ์ด์šฉํ•˜๋ฉด ์™ธ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ ์ดํ›„์—๋„ ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ ์™ธ๋ถ€ ํ•จ์ˆ˜ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ(garbage collector)๋Š” ํด๋กœ์ €(closures)๋ฅผ ํŠน๋ณ„ํ•œ ๊ณต๊ฐ„์œผ๋กœ ์—ฌ๊ธฐ๊ณ  ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ํด๋กœ์ €์— ๋‹ด๊ธด ๋ณ€์ˆ˜๋Š” ๋‚ด๋ถ€ํ•จ์ˆ˜์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ณ€์ˆ˜๋ผ๊ณ  ์—ฌ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งŒ์•ฝ ์™ธ๋ถ€ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜์ผ์ง€๋ผ๋„ ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉด ํด๋กœ์ €์— ๋‹ด๊ธฐ์ง€ ์•Š์œผ๋ฉฐ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ œ๊ฑฐ๋œ๋‹ค.

function a() {
    const grandFather = 'grandFather';
    return function b() {
        const father = 'father';
        const random = 123183521;
        return function c() {
            const son = 'son';
            return `${grandFather} > ${father} > ${son}`
        }
    }
}
console.log(a()()()); // grandFather > father > son
  • ์œ„ ์˜ˆ์ œ์—์„œ b ํ•จ์ˆ˜ ๋‚ด์— random ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค.

  • random ๋ณ€์ˆ˜๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜(c)์—์„œ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” ๋ณ€์ˆ˜์ด๋‹ค.

  • ๋”ฐ๋ผ์„œ random ๋ณ€์ˆ˜๋Š” b ํ•จ์ˆ˜ ์ข…๋ฃŒ ์‹œ ํด๋กœ์ €์— ์ €์žฅ๋˜์ง€ ์•Š๊ณ  ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ œ๊ฑฐ๋œ๋‹ค.

  • ํด๋กœ์ €(closure)๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ํŠน์„ฑ์— ์˜ํ•ด ๋™์ž‘ํ•œ๋‹ค.

  1. ์ผ๊ธ‰ ํ•จ์ˆ˜(First citizen function)์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ด๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. lexical scope๋ฅผ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๋ถ€๋ถ„์— ์˜ํ•ด scope chain์ด ์ •ํ•ด์ง„๋‹ค.

  • ํด๋กœ์ €๋ผ๋Š” ํŠน์„ฑ์„ ์ด์šฉํ•ด ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ ์™ธ๋ถ€ํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ์ž์‹ ์˜ ์ง€์—ญ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋‚ด๋ถ€ํ•จ์ˆ˜์˜ ํด๋กœ์ €์— ๋‚ด๋ถ€ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ถ€ํ•จ์ˆ˜์˜ ์ง€์—ญ๋ณ€์ˆ˜๊ฐ€ ๋‹ด๊ฒจ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

function boo(string) {
    return function(name){
        return function(name2){
            console.log(`${string} ${name} ${name2}`)
        }
    }
}
  • ์œ„ ํ•จ์ˆ˜๋Š” arrow ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
const boo = (greeting) => (name) => (name2) =>
console.log(`${greeting} ${name} ${name2}`)
boo('hi')('sony')('park') // hi sony park
  • ํด๋กœ์ €์˜ ๋ง‰๊ฐ•ํ•œ ํž˜์€ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์— ๋ฐœํœ˜๋œ๋‹ค.
const booGreeting = boo('hi');
// 5 years later
const booGreetingName = booGreeting('sony');
// 10 years later
const booGreetingName2 = booGreetingName('park');
console.log(booGreetingName2); // hi sony park
  • boo๋ฅผ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด hi๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ boo ๋‚ด๋ถ€ ํ•จ์ˆ˜์˜ ํด๋กœ์ €์— ์ €์žฅ๋œ๋‹ค.

  • ์ด ๋ง์€ ์•„๋ฌด๋ฆฌ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ๋‚ด๋ถ€ํ•จ์ˆ˜์—์„œ ์–ธ์ œ๋“ ์ง€ ์ž์‹ ์ด ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์™ธ๋ถ€ํ•จ์ˆ˜ ๋ณ€์ˆ˜์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.

  • ์œ„์™€ ๊ฐ™์€ ์ด์œ  ๋•Œ๋ฌธ์— ํด๋กœ์ €๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋งŽ์ด ํ™œ์šฉ๋˜๊ณ  ๊ทธ ๋งŒํผ ์ค‘์š”ํ•˜๋‹ค.

Exercise Closures 1

function callMeMaybe() {
    const callMe = 'Hi! I am Sony';
    setTimeout(function () {
        console.log(callMe);
    }, 4000);
}
callMeMaybe(); // Hi! I am Sony
  • ์œ„ ์˜ˆ์ œ์—์„œ callMeMaybeํ•จ์ˆ˜ ์•ˆ์— setTimeoutํ•จ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉฐ setTimeoutํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ต๋ช… ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

  • ์ต๋ช… ํ•จ์ˆ˜๋Š” callMeMaybeํ•จ์ˆ˜์˜ ๋‚ด๋ถ€ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋กœ์ €๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ํ•จ์ˆ˜ callMeMaybe์˜ ์ง€์—ญ ๋ณ€์ˆ˜ callMe์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„ ๋‚ด์—์„œ ์œ„ ํ•จ์ˆ˜์˜ ๋™์ž‘ ์ˆœ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. (์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•œ ์ˆœ์„œ์ด๋ฏ€๋กœ ์‹ค์ œ ๋™์ž‘์ˆœ์„œ์™€๋Š” ๋‹ค๋ฅด๋‹ค.)

  • callMeMaybeํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

  • call stack์— callMeMaybeํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์Œ“์ธ๋‹ค.

  • callMeMaybeํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑํ•จ์ˆ˜์ธ setTimeout ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

  • setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(์ต๋ช…ํ•จ์ˆ˜)๊ฐ€ Web API๋กœ ๋ณด๋‚ด์ง„๋‹ค.

  • callMeMaybeํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉฐ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ call stack์—์„œ ์‚ฌ๋ผ์ง„๋‹ค.

  • setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(์ต๋ช…ํ•จ์ˆ˜)๊ฐ€ Web API์—์„œ 4์ดˆ๊ฐ„ ๋จธ๋ฌด๋ฅธ๋‹ค.

  • ์‹œ๊ฐ„์ด ์™„๋ฃŒ๋˜๋ฉด callback Queue๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

  • call stack์ด ๋น„์–ด ์žˆ์œผ๋ฉด setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(์ต๋ช…ํ•จ์ˆ˜)๊ฐ€ call stack์œผ๋กœ ์˜ฌ๋ผ๊ฐ„๋‹ค.

  • setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(์ต๋ช…ํ•จ์ˆ˜)๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

    • console.log(callMe); // Hi! I am Sony
function callMeMaybe() {
    setTimeout(function () {
        console.log(callMe);
    }, 4000);
    const callMe = 'Hi! I am Sony';
}
callMeMaybe(); // Hi! I am Sony
  • callMe ๋ณ€์ˆ˜์˜ ์œ„์น˜๋ฅผ setTimeoutํ•จ์ˆ˜ ๋ฐ‘์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋„ ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๋‹ค.

  • callMe ๋ณ€์ˆ˜๋Š” const๋กœ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ˜ธ์ด์ŠคํŒ…์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.

  • ํ•˜์ง€๋งŒ ํ˜ธ์ด์ŠคํŒ…๊ณผ ๊ด€๊ณ„ ์—†์ด setTimeoutํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ callMe ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ทธ ์ด์œ ๋Š” ์œ„์˜ ๋™์ž‘ ์ˆœ์„œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋‹ค.

  • setTimeoutํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋ณด๋‹ค callMeMaybeํ•จ์ˆ˜๊ฐ€ ๋จผ์ € ์‹คํ–‰ ํ›„ ์ข…๋ฃŒ๋œ๋‹ค.

  • ๋”ฐ๋ผ์„œ callMeMaybeํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜์ธ callMe๋ณ€์ˆ˜๋Š” ์ด๋ฏธ ์„ ์–ธ๋˜์–ด ํด๋กœ์ €์— ์ €์žฅ๋œ ์ƒํƒœ์ด๋‹ค.

  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ setTimeoutํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ callMe ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

Exercise Closures 2

  • ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋ฅผ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋„๋ก ํ•ด๋ณด์ž.
let background;
function intialize(){
    background = 'โ›ฐ';
    console.log('background has been set!')
}
intialize(); // background has been set!
intialize(); // background has been set!
intialize(); // background has been set!
  • ์œ„ ์˜ˆ์ œ๋Š” ๋ฐฐ๊ฒฝํ™”๋ฉด์„ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ์ดˆ๊ธฐํ™”๋Š” ์ฒ˜์Œ ํ•œ ๋ฒˆ๋งŒ ์ง„ํ–‰๋˜๋ฉด ๋œ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์œ„ ์˜ˆ์ œ์—์„œ๋Š” intialize() ๊ฐ€ ํ˜ธ์ถœ ๋  ๋•Œ๋งˆ๋‹ค ์ดˆ๊ธฐํ™”๊ฐ€ ์ง„ํ–‰๋œ๋‹ค.
  • ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”๋ณด์ž.
let background;
function intialize() {
    let called = 0;
    return function () {
        if(called >0){
            return;
        }
        else{
            background = 'โ›ฐ';
            called++;
            console.log('background has been set!')
        }
    }
}
const startOnce = intialize();
startOnce(); // View has been set!
startOnce();
startOnce();
  • ํด๋กœ์ €(closures)๋ฅผ ์ด์šฉํ•˜๋ฉด intialize๊ฐ€ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Exercise Closures 3

  • ๋‹ค์Œ์€ ์˜ˆ์ œ๋Š” ๋ฉด์ ‘์—์„œ ๋งค์šฐ ์ž์ฃผ ๋ฌผ์–ด๋ณด๋Š” ์งˆ๋ฌธ์ด๋‹ค.

  • for loop ์•ˆ์˜ setTimeout๊ณผ ๋ณ€์ˆ˜ i

  • const arr = [1,2,3,4];
    for(var i=0; i< arr.length; i++){
        setTimeout(function () {
            console.log(i)
        }, 1000)
    }
    // output
    // 4
    // 4
    // 4
    // 4
  • ์œ„ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ’์€ 4๊ฐ€ 4๋ฒˆ ์ถœ๋ ฅ๋œ๋‹ค.

  • ๊ทธ ์ด์œ ๋Š” setTimeout์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์ „์—ญ ๋ณ€์ˆ˜ i๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • setTimeout์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ Web API์™€ callback Queue๋ฅผ ๊ฑฐ์ณ call stack์—์„œ ์‹คํ–‰๋  ๋•Œ๋Š” for ๋ฌธ์ด ๋๋‚˜๊ณ  i๊ฐ€ 4๊ฐ€ ๋œ ์‹œ์ ์ด๋‹ค.

  • ๋”ฐ๋ผ์„œ 4๊ฐ€ 4๋ฒˆ ์ถœ๋ ฅ๋œ๋‹ค.

  • ํ•˜์ง€๋งŒ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ’์€ 0,1,2,3 ์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ํ•ด๋ณด์ž.

  • ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ’์„ ์–ป๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•๋งŒ ์žˆ๋Š” ๊ฑด ์•„๋‹ˆ๋‹ค.)

  1. let ์‚ฌ์šฉ
// let ์‚ฌ์šฉ -> make 'i' as a block scope variable
const arr = [1,2,3,4];
for(let i=0; i< arr.length; i++){
    setTimeout(function () {
        console.log(i)
    }, 1000)
}
// output
// 0
// 1
// 2
// 3
  • ๋ณ€์ˆ˜ i์˜ keyword๋ฅผ var๋Œ€์‹  let ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๊ฐ„๋‹จํžˆ ํ•ด๊ฒฐ๋œ๋‹ค.
  • ๊ทธ ์ด์œ ๋Š” let keyword๋Š” ๋ธ”๋ก ์Šค์ฝ”ํ”„๋ฅผ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€์ˆ˜ i๋ฅผ for๋ฌธ ๋ธ”๋ก ์•ˆ์˜ ์ง€์—ญ๋ณ€์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
  • ๋”ฐ๋ผ์„œ setTimeout์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜ i๋Š” for ๋ฌธ ๋ธ”๋ก ์Šค์ฝ”ํ”„ ์•ˆ์— ์žˆ๋Š” i๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์ฆ‰, for ๋ฌธ ์•ˆ์—์„œ setTimeout์ด ์‹คํ–‰ ๋  ๋•Œ๋งˆ๋‹ค setTimeout์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜ i๋Š”์‹คํ–‰ ์‹œ์ ์˜ for ๋ฌธ ๋ธ”๋ก ์•ˆ์˜ i ๊ฐ€ ๋œ๋‹ค.
  1. ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ํด๋กœ์ € ์ƒ์„ฑ
// ์ฆ‰์‹œ ์‹คํ–‰ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํด๋กœ์ €(closures) ์ƒ์„ฑ
const arr = [1,2,3,4];
for(var i=0; i< arr.length; i++) {
    (function (closureI) {
        setTimeout(function () {
            console.log(closureI)
        }, 1000)
    })(i)
}
// output
// 0
// 1
// 2
// 3
  • setTimeout์„ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๋กœ ๊ฐ์ŒŒ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ฆ‰์‹œ ์‹คํ–‰ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ํ•จ์ˆ˜๊ฐ€ ๋˜๊ณ  setTimeout์€ ๋‚ด๋ถ€ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค.
  • ์ด ๋•Œ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜์—์„œ for ๋ฌธ์˜ ๋ณ€์ˆ˜ i๋ฅผ ์ธ์ž๋กœ ๋ฐ›์œผ๋ฉด ๋ณ€์ˆ˜ i(closureI)๋Š” ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜๊ฐ€ ๋œ๋‹ค.
  • setTimeout(๋‚ด๋ถ€ํ•จ์ˆ˜)๋Š” ์Šค์ฝ”ํ”„ ์ฒด์ธ์— ์˜ํ•ด ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜(์™ธ๋ถ€ํ•จ์ˆ˜)์˜ ์ง€์—ญ ๋ณ€์ˆ˜์ธ closureI ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” ํด๋กœ์ €๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ•ด๋‹น ์‹œ์ ์˜ ๋ณ€์ˆ˜i(closureI)๋ฅผ ์ €์žฅํ•œ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

Reference