https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures
클로저는 함수와 함수가 선언된 어휘적(lexical,정적) 환경의 조합이다.
var name = 'zero';
function log(){
console.log(name);
}
function wrapper(){
var name = 'nero';
log();
}
wrapper();
위 코드를 참고하면 function log와 전역범위의 관계가 클로저 관계이다.
그래서 어떤 코드를 작성하더라도 클로저 관계가 형성될 수 밖에 없는 이유이다.
for(var i = 0 ; i <100; i++){
setTimeout(function(){
console.log(i);
},i * 1000);
}
클로저의 문제는 위 코드에서 발생한다.
바로 반복문과 비동기 함수의 만남일때 오류가 발생하게 된다.
코드 상에서는 console 결과가 0~99까지 차례대로 0~99초마다 하나씩 실행되는 결과를 원한다.
하지만 실행결과는 막상 그렇게 나오지 않고
다음과 같이 100이 찍히게 된다.
각 초마다 여러개의 비동기콜백함수를 나열할 수 밖에 없다.
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[0],결과창);
// border-radius = borderRadius로 자바스크립트에서는 표현한다.
}, 1000);
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[1],결과창);
}, 2000);
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[2],결과창);
}, 3000);
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[3],결과창);
}, 4000);
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[4],결과창);
}, 5000);
setTimeout(function 비동기콜백함수 (){
공색칠하기(당첨숫자들[5],결과창);
}, 6000);
setTimeout(function 비동기콜백함수(){
공색칠하기(보너스, 보너스창);
},7000);
for(var i = 0 ; i <100; i++){
setTimeout(function(){
console.log(i);
},i * 1000);
}
//------------------------------------------------------------------
setTimeout(function (){
console.log(i) //100
}, 0 * 1000);
setTimeout(function (){
console.log(i) //100
}, 1 * 1000);
setTimeout(function (){
console.log(i) //100
}, 2 * 1000);
setTimeout(function (){
console.log(i) //100
}, 3 * 1000);
.
.
.
setTimeout(function (){
console.log(i)
}, 99 * 1000);
함수안의 변수 ex) console.log(i); 의 내부 변수 i는 '실행' 될때 결정이 된다.
따라서 만약 1초 뒤에 실행되는 순간이면 1이 아니라 100이 나오게 된다.
100이라는 값이 console값으로 나오게 되는 것을 알 수 있다.
//반복문 내의 비동기 콜백 함수 문제발생
for(var i = 0 ; i <100; i++){
setTimeout(function(){
console.log(i);
}, i * 1000);
}
//--------------------------------------------------------------------------------
function 클로저(j){ //j가 0
setTimeout(function(){
console.log(j); // 클로저 함수의 매개변수를 찾아가므로 j-->0
}, 0 * 1000);
}
function 클로저(j){ //j 가 1
setTimeout(function(){
console.log(j); //j -->1
}, 1 * 1000);
}
function 클로저(j){ //j 가 2
setTimeout(function(){
console.log(j); //j -->2
}, 2 * 1000);
}function 클로저(j){ //j 가 3
setTimeout(function(){
console.log(j); //j -->3
}, 3 * 1000);
}
console.log(j)값을 실행 하였을때 어떻게 함수 밖인 전역변수로 나가지 않을 수 있었을까?
그것은
function 클로저(j){ //j가 0
setTimeout(function(){
console.log(j); // 클로저 함수의 매개변수를 찾아가므로 j-->0
}, 0 * 1000);
}
function 클로저(){ //j가 0
var j = 0;
setTimeout(function(){
console.log(j); // 클로저 함수의 매개변수를 찾아가므로 j-->0
}, 0 * 1000);
}
클로저라고 정의 되어 있는 함수의 매개변수를 뽑아낸다면
var j = 0; 으로 표현 가능하기 때문에 전역변수로 나가지 않는 것이다.
따라서 매개변수를 변수로 생각하면 된다.
이 특성을 이용하여 반복문 내의 비동기 콜백함수 문제를 해결 할 수 있다.
//해결법
for(var i = 0 ; i < 100; i++){
function 클로저(j){
setTimeout(function(){
console.log(j);
}, j * 1000);
}
클로저(i);
}
for(var i = 0 ; i < 100; i++){
(function 클로저(j){
setTimeout(function(){
console.log(j);
}, j * 1000);
})(i);
}
//함수 즉시 실행--------------------------------------------------------------------------------
실행결과 1초마다 숫자가 1씩 증가하여 나오는 것을 볼 수 있다.
'JS' 카테고리의 다른 글
ES6 - template literal (0) | 2020.07.21 |
---|---|
ES6 - Block scope (0) | 2020.06.21 |
호이스팅 (0) | 2020.06.14 |
스코프와 스코프체인 렉시컬스코프 (0) | 2020.06.08 |
blocking(블로킹)이란? (0) | 2020.06.03 |