[바닐라코딩 프렙] Closure 예제 모음
클로저(Closure)는 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상이다.
좀 더 자세히 설명하자면, 어떤 함수 A(=외부 함수)에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우, A 함수의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상을 말한다.
오늘은 클로저의 속성을 이해할 수 있도록, Dmitri Pavlutin님의 Closure 퀴즈를 소개하려고 한다.
Q1. 아래 코드에서 출력되는 값은 무엇인가?
(function immediateA(a) { return (function immediateB(b) { console.log(a); // What is logged? })(1); })(0);
해설: immediateA 함수 parameter로 0
을 넘기며 실행되면, immediateB 함수에 parameter로 1
을 넘기며 실행한 값을 return하게 된다. A 함수가 종료되었으나, a는 가비지컬렉팅에서 제외되며, immediateB 함수에서는 외부변수인 a
변수인 0을 출력하게 된다.
Q2. 아래 코드에서 출력되는 값은 무엇인가?
let count = 0; (function immediate() { if (count === 0) { let count = 1; console.log(count); // What is logged? } console.log(count); // What is logged? })();
해설: 1
과 0
이 출력된다. immediate의 외부 scope는 count이며, global scope에 선언된 count
변수를 closure로 저장한다. 그런데, if문(블록 스코프)안에서 count가 새로 선언되어 첫 번째에서는 1
이 출력된다. 그러나, 두 번째에서는 외부 scope에 있는 count
를 참조하므로, 0
이 출력된다.
Q3. 아래 코드에서 출력되는 값은 무엇인가?
for (var i = 0; i < 3; i++) { setTimeout(function log() { console.log(i); // What is logged? }, 1000); }
해설: 4
가 네 번 출력되게 된다. i 값이 증가하며, setTimeout을 3회 실행하게 되면, log함수는 Web API를 거쳐 event queue에서 차례로 3회 실행되게 되는데, var는 전역 컨텍스트를 참조하므로, i의 값은 4이다. let을 사용하면 블록컨텍스트마다 i 값을 저장해놓을 수 있으나, var을 유지할 경우, 클로저를 활용하여 이를 해결할 수 있다.
for (var i = 0; i < 3; i++) {
setTimeout(function(i) {
return function log() {
console.log(i); // What is logged?
}}(i), 1000);
}
이 경우, 각 setTimeout의 function에서 넘겨받은 인수 i에 대해 내부함수에서 클로저가 발생하여, event queue에서 내부 함수가 실행될 때, 실행 시의 컨텍스트를 참조하여 i 값을 출력하므로, 0,1,2가 출력되게 된다.
Q4. 아래 코드에서 출력되는 값은 무엇인가?
function createIncrement() { let count = 0; function increment() { count++; } let message = `Count is ${count}`; function log() { console.log(message); } return [increment, log]; } const [increment, log] = createIncrement(); increment(); increment(); increment(); log(); // What is logged?
해설: 'Count is 0'
가 출력되게 된다. increment()
가 3회 출력되어, count
의 값은 3이 되었으나, message 변수는 'Count is 0'
를 가지고 있으며, log함수는 message 변수를 참조하므로, 위와 같이 출력된다.
function log() {
let message = `Count is ${count}`;
function log() {
console.log(message);
}
}
message를 안에 선언하여, message의 count가 외부 scope를 참조하도록 해야, count의 상승분을 반영할 수 있다.
Q5. 아래 코드를 수정하여,
stack.item
이 접근불가능하게 만드시오.function createStack() { return { items: [], push(item) { this.items.push(item); }, pop() { return this.items.pop(); } }; } const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5 stack.items; // => [10] stack.items = [10, 100, 1000]; // Encapsulation broken!
해설: items
를 createStack()
의 scope에 넣어서, 클로저로 변수를 접근하게 하며, 외부에서 프로퍼티로 접근하지 못하게 한다. this
도 붙일 필요가 없다. items 변수가 클로저로 저장되기 때문이다.
function createStack() {
// Write your code here...
const items = [];
return {
push(item) {
items.push(item);
},
pop() {
return items.pop();
}
}
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => undefined
Q6. 아래 코드를 작성하여,
multifly()
함수를 완성하시오.function multiply(num1, num2) { // Write your code here... if (num2 !== undefined) { return num1 * num2; } return function doMultifly(num2) { return num1 * num2; } } multiply(4, 5); // => 20 multiply(3, 3); // => 9 const double = multiply(2); double(5); // => 10 double(11); // => 22
해설: multiply
함수의 경우, 두 인자를 받지만, num2가 생략되었을 경우, return 된 doMultiply
함수에서 num1은 클로저 변수로 저장된다. 이 때문에, num2만 인자로 받아 연산이 가능하다.
Author And Source
이 문제에 관하여([바닐라코딩 프렙] Closure 예제 모음), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hw8129/바닐라코딩-프렙-Closure-예제-모음저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)