상세 컨텐츠

본문 제목

[모각코][JavaScript] 값으로서 함수와 콜백

JavaScripts

by <감귤> 2021. 7. 18. 19:10

본문

값으로서의 함수

1.함수는 값으로 사용가능

JavaScript에서는 함수도 객체다. 다시 말해서 일종의 값이다. 거의 모든 언어가 함수를 가지고 있다. JavaScript의 함수가 다른 언어의 함수와 다른 점은 함수가 값이 될 수 있다는 점이다.

function a(){}

위의 예제에서 함수 a는 변수 a에 담겨진 값이다. 따라서 아래와 같은 방식으로 써도 무방하다.

let a = function(){} //함수

또한 함수는 객체의 값으로 포함될 수 있다. 이렇게 객체의 속성 값으로 담겨진 함수를 메서드(method)라고 부른다.

a = {
	b: function(){ //메서드
    
    }
}

코드 설명:

a라는 객체에 b라는 key가 있고 그 key에 function( ){ }이라는 value가 대응된다.

따라서 함수는 객체에 저장될 수 있다.

여기서 key에 해당하는 b는 특정 값(value)를 저장하고 있기 때문에 "변수"의 역할을 하고 있다.

이를통해 알 수 있듯이, key는 변수같은 역할을 수행하고 있고, 객체(현재의 경우 변수 a에 해당) 안에서 변수의 역할을 하는 것을 "속성(property)"라고 한다. 그리고 그 속성에 저장되어있는 값(value)이 함수라고 한다면 그 함수를 메서드(method)라고 부른다.

=> a라는 변수에 담겨있는 속성인 b의 값은 함수이다. 이때의 함수를 메서드라고 부른다.

  

2. 함수는 인자로 전달가능

함수는 값이기 때문에 다른 함수의 인자로 전달 될수도 있다. 아래의 예제를 보자.

function cal(func, num){
	return func(num)
}

function increase(num){
	return num+1
}

function decrease(num){
	return num-1
}

alert(cal(increase, 1)) // -> 2
alert(cal(decrease, 1)) // -> 0

 

alert(cal(increase, 1)) 이 부분이 어떻게 작동되는지 살펴보자

increase함수가 cal함수의 첫번째 인자로 전달이 되었고, cal함수 내부에선 첫번째 인자의 값뒤에 괄호를 붙여서 호출한다. 즉, 함수는 값이기 때문에 다른함수의 인자로 전달 될 수 있다.

function cal(func, num){
	let func = increase(num){
    	return num + 1
    }
    return func(num)
}

위와 같은 작동을 통해 2가 출력되고 alert(cal(decrease, 1))의 경우에도 유사하게 작동하여 0을 출력하게 된다.

 

3. 함수는 리턴 값으로 사용가능

함수는 함수의 리턴 값(반환 값)으로도 사용할 수 있다.

function cal(mode){
	let funcs = {
    	'plus': function(left, right){return left + right}
        'minus': function(left, right){return left - right}
    }
    return funcs[mode];
}

alert(cal('plus')(2,1)); // -> 3
alert(cal('minus')(2,1)); // -> 1

cal('plus') 이 부분이 function(left, right){return left + right} 이 부분에 매칭된다.

그리고 (2, 1)부분을 통해 함수가 호출되고 인자가 전달됨으로써 funcs['plus']의 return으로 3(2+1)이 된다.

 

4. 함수는 배열의 값으로 사용가능

let process = [
    function(input){ return input + 10; },
    function(input){ return input * input; },
    function(input){ return input / 2; }
];
let input = 1;
for(let i = 0; i < process.length; i++){
	input = process[i](input); // process의 배열의 원소인 function(input)들을 하나씩 접근함
}

alert(input); // -> 60.5

for문의 첫번째로는 process배열의 첫번째 원소에 input이 1로 전달되므로 그때 assign되는 input의 최종값은 11(1+ 10)

이고 for문의 두번째로는 process배열의 두번째 원소에 input이 11로 전달되므로 그때 assign되는 input의 최종값은 121(11 * 11)이다. 마지막으로는 121 / 2 = 60.5가 alert(경고창)로 나온다. 

=> 중간정리

JavaScript에서 함수는 1.변수 2.매겨변수(인자) 3.리턴 값  4.배열의 원소 로 다양하게 활용될 수 있는다.

이렇게 다양하게 활용될 수 있는 데이터를 first-class citizen(or object or entity or value)로 부른다. 

즉, JavaScript에서 함수는 first-class citizen에 해당하기 때문에 앞서 살펴본 바와 같이 다양한 용도로 쓰일 수 있다.

이제, 이러한 특성이 어디에서 활용될 수 있는지 살펴보자.

콜백(Callback)

처리의 위임

값으로 사용될 수 있는 특성을 이용하면 함수의 인자로 함수로 전달할 수 있다. 값으로 전달된 함수는 호출될 수 있기 때문에 이를 이용하면 함수의 동작을 완전히 바꿀 수 있다. 인자로 전달된 함수 sortNumber의 구현에 따라서 sort의 동작방법이 완전히 바뀌게 된다.

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

numbers는 배열객체에 해당한다. 그리고 배열객체 안에는 sort라는 메서드(정렬하는 기능)가 정의되어있다.

※ 여기서 sort는 객체 안에 있기 때문에 메서드라고 부른다.

이러한 배열객체와 sort같은 메서드는 는 JavaScript에서 내부적으로 지원해주는 기능이기 때문에 

이를 내장객체, 내장메서드, 또는 빌드인 객체(built-in object), 빌트인 메서드(built-in method)라고 부른다.

이에 반해 우리가 정의하고 사용하는 객체, 메서드는 사용자 정의 객체, 사용자 정의 메서드라고 부른다.

sort함수가 내부적으로 어떻게 되어있는지 알아야할 필요가 있다.

let numbers = [20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
let sortfunc = function(a, b){
  console.log(a, b);
  if(a > b){
      return 1;
  }
  else if(a < b){
      return -1;
  }
  else {
      return 0;
  }
}

console.log(numbers.sort(sortfunc));

20  1, 1  6, 20  6, 9  6, 2  6, 8  6, 3  6, 7  6, 4  6, 10  6 5  6, 1  2, 2  3, 3  4, 4  5, 10  7, 10  8, 7  8, 10  9, 8  9, 10  20

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20]

이 출력으로 나온다. 보면 알 수 있듯이 a와 b의 비교를 통해 return 되는 값이 양수, 음수, 0인지에 따라 특정 알고리즘을 통해 정렬해서 그 결과를 보여주는 것을 알 수 있다. 이를 통해 앞선 코드에서 긴 조건문 대신 return a - b;를 통해 우리가 원하는 오름차순 정렬한 결과를 얻을 수 있었다. (return b - a; 일 경우, 내림차순 정렬이 된다.)

 

위 코드에서 sortfunc가 콜백(callback)함수가 된다. 

이 콜백함수(sortfunc)를 인자로 받는 sort메서드는 내부적으로 호출되고, 이 sort메서드가 동작하는 기본적인 방법을 우리가 변경할 수 있게 된 것이다. 즉, 값으로서 함수를 사용할 수 있기 때문에 sort메서드의 동작 방법을 값을 전달하는 방법을 통해 변경할 수 있다. 라는 것이 바로 콜백(callback)이고 이러한 콜백이 가능한 이유는 자바스크립트에서 함수가 값이기 때문에 가능한 것이다.

비동기 처리

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

저 "변수" 에 해당하는 내용을 보기 위해 클릭하면

url이 바뀌면서 웹페이지 전체가 새로 다운로드 되는 것이다.

이렇게하는 것이 일반적인 방법이다. 즉, 어떠한 정보를 웹페이지 상에서 갱신하고 싶을때 페이지 전체를 다운로드 받아서 그 전체를 화면에 표시하는 것이 일반적인 방법이다.

이에 반해, 우측 상단에 있는 "내 컨텐츠"는 클릭해서 현재 웹페이지 상에 없는 정보를 보고있지만 url도 그대로 이고 웹페이지의 변동이 전혀 느껴지지 않는다. 이것이 가능한 이유는 현재 보이고 있는 "모듈", "코스"의 리스트를 서버에 요청해서 가져온다음에 그것을 화면에 표시해서 그런것이다. 

-> Ajax(Asynchronous JavaScript and XML)를 썼기에 가능한 것이다. (아래 사진은 F12로 개발자도구를 통해 확인한 결과이다.)

Reference

인프런_자바스크립트 언어 기본 - javascript(생활코딩)

관련글 더보기