자바스크립트 동작원리

주니·2021년 12월 14일
2

js문법

목록 보기
1/3


[그림 참조]https://baeharam.github.io/posts/javascript/jshow-javascript-works/

자바스크립트는 위와 같은 구조를 가지고 실행된다. 자바스크립트에서 실행되는 함수는 stack에 들어가고 맨 위 부터 차례대로 실행되게 된다. stack은 LIFO(Last In First Out)에 따라 실행되기 때문이다.

평소 작동상태는?(동기)

function test(){
    console.log('test');
}

function qux(){
    test();
    console.log('qux');
}

function bar(){
    qux();
    console.log('bar');
}

function foo(){
    bar();
    console.log('foo');
    
}

foo();

위와 같은 코드가 실행된다면 foo, bar, qux, test 순으로 스택에 쌓이게 된다. 그리고 가장 마지막에 실행된 test부터 qux, bar, foo 순으로 실행되게된다.

<출력>
test
qux
bar
foo

요렇게 출력될 것이다.

비동기 처리를 해야하는 함수는?

비동기처리 문제

console.log(1+1);
setTimeout(()=>{console.log(2+2)}, 1000);
console.log(3+3);

이 코드를 실행하면 어떤 결과가 출력될거라고 생각하는가? 나 같이 자바스크립트의 작동원리를 몰랐던 상태였다면 당연히 "2 4 6"순으로 출력될 것으로 예상할 것이다.

<출력>
2
6
4

하지만 출력하게 되면 뜬금없이 4가 마지막에 실행되는 것을 볼 수 있다.

비동기처리 작동 방법

스택에 setTimeOut, Ajax요청, 이벤트리스너와 같이 정해져 있는 몇몇 API에 대해서 자바스크립트는 비동기처리를 요구한다.

작동 방법은 다음과 같다.
setTimeOut이 stack에 들어오게되면 이거 뭐야 대기실로 보내!
-> 대기실에서 1초 동안 기다려야지..
-> 시간 다 됐다. 큐로 가야지!!
-> 아.. 스택 전부 빌때까지 못 간대 ㅜㅜ, 스택이 다 비면 가자.
-> 스택이 다 비게 되면 setTimeOut에 있던 콜백함수들이 스택에 쌓이게 되고 이것이 실행되는 것이다.

그래서 위와 같이 4가 제일 마지막으로 출력되는 것이다. setTimeout의 설정 시간을 0밀리세컨드로 한다고 하더라도 스택이 다 빌때까지 들어가지 못 하기에 출력값은 동일하다.

for (var i = 0; i<10; i++){
    setTimeout(()=>{console.log(i)},2000);
};

그렇다면 위와 같은 코드의 실행값은 무엇이 될까??? "0 1 2 3 4 5 ... 9"일까?
아니다. "10 10 10 ... 10"이 실행되게 된다.

i=0일때 stack에 가자마자 setTimeout은 대기실로 보내버리게된다. 이것이 반복되게 되면 백그라운드에서 setTimeout 6개가 2초를 기다리고 있게 될 것이다. 하지만 for문의 i는 스택에서 차례대로 실행되어 결국 i=10을 heap에 저장하게 된다. 그래서 후에 스택으로 돌아온 setTimeout의 콜백함수들은 heap의 i값을 들고오게 되고 10이 10번 호출되게 되는 것이다.

위와 같을 때 for문에서 let 키워드를 사용하시면 for문이 반복될 때마다 새로운 렉시컬 환경을 생성합니다. 그렇게하면 i값을 기억하기 때문에 올바른 결과값을 나타낼 수 있게 된다.

for(i=1; i<6; i++){
    (function(x){
      setTimeout(function(){
        console.log(x);
      }, 1000*x);
    })(i);
  }

혹은 이와 같이 즉시실행함수를 사용할 수도 있다.

비동기 처리 방식은 어떻게 하여야 하는가?!

콜백, 프라미스, async await을 통해서 다룰 수 있다.! 이것은 다음 포스팅에서 다루도록 하겠다.

profile
달팽이처럼

0개의 댓글