2019๋ 7์ 1์ผ
- ํด๋ก์ (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)๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ค์ ๋ ๊ฐ์ง ํน์ฑ์ ์ํด ๋์ํ๋ค.
-
์ผ๊ธ ํจ์(First citizen function)์ด๊ธฐ ๋๋ฌธ์ ํจ์๋ฅผ ๋ฆฌํด๊ฐ์ผ๋ก ์ ๋ฌํ ์ ์๋ค.
-
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 ๋ด๋ถ ํจ์์ ํด๋ก์ ์ ์ ์ฅ๋๋ค. -
์ด ๋ง์ ์๋ฌด๋ฆฌ ์๊ฐ์ด ์ง๋๋ ๋ด๋ถํจ์์์ ์ธ์ ๋ ์ง ์์ ์ด ์ฐธ์กฐํ๊ณ ์๋ ์ธ๋ถํจ์ ๋ณ์์ ์ ๊ทผ ํ ์ ์์์ ์๋ฏธํ๋ค.
-
์์ ๊ฐ์ ์ด์ ๋๋ฌธ์ ํด๋ก์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋๋ฐ์์ ๋ง์ด ํ์ฉ๋๊ณ ๊ทธ ๋งํผ ์ค์ํ๋ค.
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 ๋ณ์์ ์ ๊ทผํ ์ ์๋ค.
- ํด๋ก์ ๋ฅผ ์ด์ฉํด ์ด๊ธฐํ ํจ์๋ฅผ ํ ๋ฒ๋ง ํธ์ถ๋๋๋ก ํด๋ณด์.
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๊ฐ ๋จ ํ ๋ฒ๋ง ํธ์ถ๋๊ฒ ํ ์ ์๋ค.
-
๋ค์์ ์์ ๋ ๋ฉด์ ์์ ๋งค์ฐ ์์ฃผ ๋ฌผ์ด๋ณด๋ ์ง๋ฌธ์ด๋ค.
-
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 ์ด ์ถ๋ ฅ๋๋ ๊ฒ์ด๋ผ๊ณ ํด๋ณด์.
-
์ํ๋ ๊ฒฐ๊ณผ๊ฐ์ ์ป๊ธฐ ์ํด ๋ค์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ด์ฉํ ์ ์๋ค. (์ด ๋ ๊ฐ์ง ๋ฐฉ๋ฒ๋ง ์๋ ๊ฑด ์๋๋ค.)
- 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
๊ฐ ๋๋ค.
- ์ฆ์ ์คํ ํจ์๋ฅผ ํตํ ํด๋ก์ ์์ฑ
// ์ฆ์ ์คํํจ์๋ฅผ ํตํด ํด๋ก์ (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
)๋ฅผ ์ ์ฅํ๋ค. - ์ด๋ฅผ ํตํด ์ํ๋ ๊ฒฐ๊ณผ๊ฐ์ ์ป์ ์ ์๋ค.