본문 바로가기

프로그래밍 공부/JavaScript

JavaScript - 자바스크립트의 실행 순서

웹 브라우저에  처리를 부탁하는 함수

다른 프로그래밍 언어에는 쓰레드(Thread)라는 개념이 있는데 쉽게 코드를 읽어 내려가는 것을 뜻한다. 그리고 어떤 프로그래밍 언어들은 이러한 쓰레드를 여러개를 만들 수 있다. 자바스크립트는 쓰레드는 1개가 고정이다. 

alert('A');

setTimeout(function(){

      alert('B');

}, 0);

alert('C');

위의 코드를 실행하면 보통은 위에서 부터 순서대로 alert('A') -> alert('B') -> alert('C') 순서로 차례대로 실행이 될 것 같지만 실제로는 alert('A') -> alert('C') -> alert('B') 순으로 실행이 된다. 이유로는 자바스크립트 함수 중에는 웹 브라우저의 처리를 부탁하는 함수가 존재하는데, 대표적으로 위의 타이머 함수와 웹 요청 관련 함수가 있다. 이것은 웹 브라우저가 처리를 하고 처리가 완료되었다는 것을 자바스크립트에 알려준다.

 

이러한 함수들은 현재 실행중인 다른 코드의 실행이 끝나기 전에는 실행이 되지 않는다.

반복문과 스코프

자바스크립트의 실행 순서 때문에 발생하는 문제는 또 있다. 먼저 스코프(scope)의 개념을 알아야하는데 스코프는 유효범위를 말한다. 자바스크립트에서 유효범위는 전역 스코프와 지역 스코프가 있다. 그리고 자바스크립트는 유효범위 단위가 블록 단위가 아니라 함수 단위로 정의된다. 따라서 조건문이나 반복문을 사용한다 하더라도 모두 같은 함수내에 있다면 함수 단위로 스코프가 지정이 되는 자바스크립트에서는 변수의 사용이 가능하다.

// global_scope의 스코프는 스크립트 전체 영역

var global_scope="global";

function A(){

// local_scope_a의 스코프는 function A의 중괄호 영역

    var local_scope_a="a";

    function B(){

// local_scope_b의 스코프는 function B의 중괄호 영역

        var local_scope_b="b";

        function C (){

// local_scope_c의 스코프는 function C의 중괄호 영역

            var local_scope_c="c";

         }

    }

}

아래는 var과 let을 사용할 때의 차이를 나타낸 표이다.

var을 사용하는 경우 let을 사용하는 경우

// var은 전역변수, 따라서 3, 3, 3 순으로 출력

for(var i=0i<3i++){

    setTimeout(function(){

            alert(i);

    }, 0);

}

// let은 지역변수, 따라서 0, 1, 2 순으로 출력

for(let j=0j<3j++){

    setTimeout(function(){

            alert(j);

    }, 0);

}

setTimeout은 이전에 설명에도 있듯 다른 코드의 실행이 끝난후에 실행이 되고 이전에는 예약이 되는 식으로 대기를 하게 된다. 그런데 var로 변수를 선언하게 되면 할당되는 값이 유동적으로 변하게 된다. 반복문이 먼저 실행이 되기 때문에 var로 선언한 i의 값이 0, 1, 2 그리고 마지막인 3으로 할당이 되고 반복문을 나오게 되고 setTimeout()함수가 이때부터 실행이 된다. 그런데 i값은 반복문 코드가 실행이 되면서 i=3으로 바뀌어 있기 때문에 setTimeout() 함수내에 alert(i)는 3만 3번 출력을 하게 된다.

 

var은 함수 단위로 스코프가 정해지지만 위의 var을 사용할때는 var이 함수의 밖에 있기 때문에 스코프가 스크립트 전체로 바뀌게 된다. 따라서 함수 내부에 0, 1, 2가 저장되지않고 최종적으로 할당된 3이라는 값만 출력을 하게 되는 것이다.

 

반대로 let은 var과는 다르게 함수 단위로 스코프가 지정되는게 아니라 블록 단위로 스코프가 지정이 되고, let은 변수를 두 번 이상 선언이 불가능하다. 따라서 for 반복문 안의 let은 for 반복문이라는 블록 단위 스코프를 가지게되고 for 반복문 밖에서는 사용이 불가능하게 된다. 실행이 되면 let은 차례대로 0, 1, 2를 반환하고 setTimeout() 함수도 0, 1, 2를 alert()으로 예약을 하게 되고, for 반복문이 종료되면 alert(0), alert(1) 그리고 alert(2)를 출력하게된다.

for(var k=0k<3k++){

     (function (closure_k){

          setTimeout(function(){

                alert(closure_k);

          }, 0);

     })(k);

}

그 외에도 클로저를 사용해 내부 함수 안에 0, 1, 2 변수를 복사해 두는 방법이 있다. 반복문이 실행되는 동안 function (closure_k) 함수 안에 값을 저장해 두는 방법이다.

자바스크립트의 실행 순서.html
0.00MB

기본 매개변수

매개변수를 입력하지 않을 때, 매개변수를 강제로 초기화 하는 것을 기본 매개변수라고 한다. 쉽게 '매개변수가 undefined라면, 값을 넣는다'는 형태로 만들면 된다. 세가지 형태가 있고 아래와 같다.

function test(abc){

// a의 종류가 undefind일때 a=10

            if(typeof(a)=="undefined"){

                a=10;

            }

// b가 false(undefined는 false로 변환됨)일때 b=20

            if(!b){

                b=20;

            }

// 논리 연산자를 사용해 c=c||30

            c=c||30;

            

            alert(a + b + c);

}

test();

세가지 방법중에서 맨 위에 있는 방법이 가장 안전하고, 세 번째에 있는 논리 연산자를 사용한 것은 사용자가 0이나 ""등을 입력 할 때 false로 취급이 되어 의도하지 않은 결과가 나올 수 있기 때문에 사용에 주의해야한다.

function test(a=10b=20c=30){

      alert(a + b + c);

}

test();

ECMAScript 6에서는 더 간단해 졌는데, 직접 매개변수에 값을 넣어주는 방법이다. 이렇게 되면 매개변수 a, b, c가 입력이 되지 않았을때 직접 넣은 값으로 함수가 실행이 되게 만든다. 주의할 점은 위의 기본매개변수는 뒤쪽에 붙여서 사용한다.

function test(ab=20c=30){

      alert(a + b + c);

}

test(10); 

이유는 c를 비워두면 아래에 값을 넣을때 c에 값을 넣을 방법이 없기 때문이다.

기본 매개변수.html
0.00MB