JavaScript_05_fin

콜백

처리의 위임

함수가 값으로 사용될 수 있는 특성을 이용하면 함수의 인자로 함수를 전달할 수 있다.
값으로 전달된 함수는 호출 될 수 있기 때문에 이를 이용하면 동작을 완전히 바꿀 수 있다.

예시) 객체에 속한 메소드(함수)를 이용해 이해해보자.

  1. var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];  
    alert (numbers.sort()); // [1, 10, 2, 20, 3, 4, 5, 6, 7, 8, 9]

     

결과를 보면 3보다 10이 먼저 나오는 등의 이상한 결과를 볼 수 있다.
이건 내장 함수인 sort 때문인데 sort의 정의를 보면

  1. sort(sortfunc)  

     

인자명

데이터형

필수/옵션

설명

sortfunc

function

옵션

원소들 간에 무엇이 우선인지를 판단한다

이와 같이 sort는 배열의 방식을 자신이 정할 수 있다.
정하지 않으면 기본 적인 동작을 하기 때문에 10이 3보다 먼저 나오는 것이다.

자세한 예를 들진 않고 결과만 설명하면 sort는 인자로 음수를 받게 되면 앞에 들어오는 수가 뒤에 오는 수 보다 작다고 인식한다.

Sort의 동작 방식과 콜백(처리 위임)을 사용하면 원하는 순서대로 나열 할 수 있다.

  1. function sortNumber(a,b){  
    // 위의 예제와 비교해서 a와 b의 순서를 바꾸면 정렬 순서가 반대가 된다.   
    return b-a;  
    }  
    var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];  
    alert(numbers.sort(sortNumber)); // [20,10,9,8,7,6,5,4,3,2,1]

     

비동기 처리

콜백은 비동기처리에서도 유용하게 사용된다. 시간이 오래걸리는 작업이 있을 때 이 작업이 완료된 후에 처리해야 할 일을 콜백으로 지정하면 해당 작업이 끝났을 때 미리 등록한 작업을 실행하도록 할 수 있다.

해당 실습은 서버 환경에서만 동작하므로 영상을 참,

 

 

클로저

클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.

내부, 외부 함수

  1. function outter(){// 외부 함수의 시작
    var title = 'coding everybody';    
    function inner(){// 내부 함수의 시작
    alert(title);  
    }                 // 내부 함수의 끝  
    inner();  
    }   // 외부 함수의 끝
    outter(); //coding everybody

     

위 예제를 보면 3. ~ 5. 까지가 내부 함수 이고 그것을 감싸고 있는 1. ~ 7. 까지가 외부 함수이다.

여기서 주목 하고 싶은 것은 외부 함수의 지역 변수인 title을 내부 함수에서 부를 수 있다는 것이다.

클로저의 특징

  1. function outter(){  
    var title = 'coding everybody';    
    return function(){          
    alert(title);  
    }  
    }  
    inner = outter();  
    inner();    // coding everybody

     

위 예제를 보면 7. 에서 outter()함수를 호출하고 return값으로 함수를 반환하고 inner라는 변수의 저장한다.
이후 8. 에서 inner()함수를 호출하면 “coding everybody” 라는 함수가 표현 된다.

여기서 눈여겨봐야 하는 것은 분명히 2. 에 있는 변수 title는 return을 했기에 4. 에서 호출하는alert(title); 를 실행 시킬 수 없어야 하지만 호출이 가능하다는 것이 클로저의 특징이다.

Ex) 클로저를 이용한 좀 더 실용적인 예제

  1. function factory_movie(title){  
    return {  
    get_title : function (){  
    return title;  
    },  
    set_title : function(_title){  
    title = _title  
    }  
    }  
    }  
    ghost = factory_movie('Ghost in the shell');  
    matrix = factory_movie('Matrix');  
    alert(ghost.get_title());    // Ghost in the shell
    alert(matrix.get_title());   // Matrix
    set_title('공각기동대 ');  
    alert(ghost.get_title());    // 공각기동대
    alert(matrix.get_title());   // Matrix
    ~ 10. 까지는 get title와 set title 라는 함수를 가진 객체를 return하고 있다.

     

get title는 외부 함수가 받은 title라는 인자를 반환 하는 역할을 하고 (2. ~ 5.)
set title는 set title가 받은 _title를 외부 함수의 저장된 title에 넣는 역할을 한다. (6. ~ 8.)

  1. 에선 변수 ghost 에 “Ghost in the shell”라는 title을 가진 객체를 담고,
    12. 에선 변수 matrix에 “Matrix”라는 title을 가진 객체를 담는다.
  2. ~ 15. 19. ~ 20. 에서 처럼 이후 내장 함수인 get_title를 통해 저장된 title을 볼 수 있으며
  3. 에서처럼 내장 함수인 set_title를 통해 저장된 title을 변경 할 수 있다.

또한 여기서 만들어진 외부 함수의 title은 private변수가 되어 set_title이나 get_title으로만 변경/접근이 가능하다.

클로저의 응용

배열 arr[0 ~ 4] 까지에 0 ~ 4를 넣는 예제를 한번 만들어 보자.

  1. var arr = []  
    for(var i = 0; i < 5; i++){  
    arr[i] = function(){  
    return i;  
    }  
    }  
    for(varindex in arr) {  
    log(arr[index]());  
    }    // 5, 5, 5, 5, 5

     

얼핏 보면 2. 에서 for문을 돌면서i를 return 하여 arr[i]에 넣는 것처럼 보이지만 실행 결과는 5, 5, 5, 5, 5가 나오게 된다. 왜냐하면 4. 에서의 i값은 우리가 정의한 3. ~ 5. 함수의 외부 변수의 값이 아니기 때문이다.

그러므로 3. ~ 5.에게 외부 함수를 만들어 외부 변수를 참조하게 하면 제일 처음 원하는 결과를 얻을 수 있게 된다.

  1. var arr = []  
    for(var i = 0; i < 5; i++){  
    arr[i] = function(id) {  
    return function(){  
    return id;  
    }  
    }(i);  
    }  
    for(varindex in arr) {  
    log(arr[index]());  
    }    // 0, 1, 2, 3, 4

     

3. ~ 7. 외부 함수는 (i)를 인자로 받고 외부 변수 (id)에 값 넣어 5. 에서 그 값을 return한다.
그렇게 되면 arr[i] 값에는 우리가 원하는 0 ~ 4까지의 값이 들어가게 된다.

 

 

arguments (객체)

아래 예제를 보자

  1. function sum(){ // 전달되는 인자가 없다.  
    var i, _sum = 0;      
    for(i = 0; i < arguments.length; i++){ 
    write(i+' : '+arguments[i]+'<br />');  
    _sum += arguments[i];  
    }     
    return _sum;  
    }  
    write('result : '+ sum(1,2,3,4)); // 전달되는 인자가 있다.  

     

1. 을 보면 sum이라는 함수의 인자가 없어도 9. 에서처럼 인자를 전달 할 수 있다.

이게 가능한 이유는arguments라는 함수 안에서 사용할 수 있도록 전달 받은 인자들을 자동으로 배열에 넣어주는 기능을 가진 약속된 이름의 배열이 있기 때문이다.

매개변수의

  1. function one(arg1){  
    log(  
    'one.length', one.length,  
    'arguments', arguments.length  
    );  
    }  
    one('val1', 'val2');  // one.length 1 arguments 2 
    functiontwo(arg1, arg2){  
    log(  
    'two.length', two.length,  
    'arguments', arguments.length  
    );  
    }  
    two('val1');  // two.length 2 arguments 1

     

7. 에서 one을 호출 할 때 2개의 인자를 보내고있고 one에서 지정된 매개 변수는 1개 이다.
이때 one.length와 결과와 arguments.length의 결과가 다른데 그 이유는 arguments는 매개 변수의 개수가 아닌 전달 받은 인자의 수만큼의 length를 가지고 있기 때문이다.

이를 이용해서 func.length값과 arguments.length 값을 비교해 정해진 매개변수만큼 인자가 왔는지 확인이 가능하다.

 

글의 문제가 있다면 댓글을 달아 주세요.

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.