본문으로 바로가기

값으로서의 함수


자바스크립트에서는 함수도 객체입니다.

다시말해서 일종의 값입니다. 

거의 모든 언어가 함수를 가지고 있지만 자바스크립트 함수가 다른 언어의 함수와 다른 점은 함수가 값으로 사용될 수 있다는 점입니다.




그렇다면 값이라는 것은 어떤 특징을 가지고 있을까?

예를 들어, 값은 어떠한 변수에 'value'라는 문자열을 담을 수 있습니다.

var a = 'value'; 

값은 어떠한 변수에 'value'라는 문자열을 담을 수 있습니다.

value 라는 문자열을 담을 수 있는 이유는 value 라는 것이 값이기 때문입니다.

자바스크립트의 함수 역시도 변수에 담을 수 있는 속성을 가지고 있다고 할 수 있는데 이는 다른 언어의 함수와 다른 점입니다.


function a() {}


위에 정의된 함수는 a라는 자바스크립트 변수에 담겨진 일종의 값이라는 점입니다.

이를 일컬어 함수 변수라고도 합니다.


위의 함수를 다른 방식으로 정의하면 다음과 같습니다.

var a = function() {}

이렇게 하면 함수가 분명하게 값으로 쓰였다는 것을 이해할 수 있습니다.

즉, 함수의 정의가 a 변수에 담겼으며 함수가 값으로 쓰인 것입니다.



var a = {
b:function(){ // b key이지만 변수의 역할을 하며 이러한 key를 속성(property)라고 부른다.
}
};


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

함수는 값으로 쓰일 수 있기 때문에 객체에 저장될 수 있는 것입니다.





함수는 리터럴에 의해 생성

함수는 함수 리터럴 표현식이 가능하다.


var sum = new Function('x','y','return x+y');
sum(2,3);

var sum2 = function(x,y) {
return x + y;
};
sum2(2,3)


var fn = new Function(); 함수를 생성하지만 이러한 표현으로는 늘어나는 코드량으로 인해 가독성이 떨어진다.

그래서 함수 단축표현식은 var fn = function() {} 으로 함수 리터럴을 사용할 수 있다.





함수는 함수의 인자로 전달 가능

함수는 값이기 때문에 다른 함수의 인자로도 전달될 수가 있습니다. 


다음의 코드를 살펴보겠습느다.


function cal(func, num){
return func(num)
}
function increase(num){
return num+1
}
function decrease(num){
return num-1
}
console.log(cal(increase, 1));
console.log(cal(decrease, 1));


cal(increase,1)을 실행하면 increase와 값 1이 함수 cal의 인자로 전달됩니다. 

함수 cal은 첫번째 인자로 전달된 increase를 실행하는데 이 때 두번째 인자의 값이 1을 인자로 전달합니다. 

함수 increase은 계산된 결과를 리턴하고 cal은 다시 그 값을 리턴합니다.






함수는 함수의 리턴값으로 리턴이 가능

함수는 함수의 리턴값으로도 사용할 수가 있습니다.


function cal(mode){
var funcs = {
'plus' : function(left, right){return left + right},
'minus' : function(left, right){return left - right}
}
return funcs[mode]; // 리턴 값으로 함수를 사용
}

console.log(cal('plus')(2,1)); // 3
// cal('plus') 이 부분은 funcs.puls, funcs[plus]이므로 cal('plus')의 값으로
// function(left, right){return left + right}을 가지고 있는 것이고 이 값인 함수를 호출하기 위해서

// cal('plus')() 이중 호출의 형태를 보이게 된 것이다.
console.log(cal('minus')(2,1)); // 1







함수는 동적으로 프로퍼티를 생성 및 할당이 가능

계속해서 강조하지만 자바스크립트에서는 함수도 객체입니다.

즉, 함수의 기본 기능인 코드 실행뿐만 아니라, 함수 자체가 일반 객체처럼 프로퍼티를 생성하고 할당이 가능하다는 것입니다.


// 함수 선언문 방식으로 add() 함수 정의
function add(x,y) {
return x + y;
}

// add()함수도 객체처럼 프로퍼티를 가질 수 있다.
// add()함수 객체에 result, status 프로퍼티를 추가해 본다.
add.result = add(3,4);
add.status = 'complete';

console.log(add.result); // 7
console.log(add.status); // 'complete'


add()함수는 마치 일반 객체처럼 result 프로퍼티를 동적으로 생성하고 add()함수를 호출한 결과를 저장한 것을 확인 할 수가 있습니다.

이렇게 일반객체의 접근방식처럼 add.result, add.status를 이용해 접근이 가능합니다.


다시말해서 자바스크립트에서 함수는 특정기능의 코드를 수행할 뿐만 아니라, 일반 객체처럼 자신의 프로퍼티를 가질 수 있는 특별한 객체라고 볼 수 있습니다.


function cal(mode){
var funcs = {};
funcs[mode] = function(left, right){return left + right};

return funcs[mode]; // 리턴 값으로 함수를 사용
}
console.log(cal('plus')(2,1)); // 3 => 동적으로 프로퍼티를 추가






변수나 배열의 요소, 객체의 프로퍼티 등에 할당이 가능

함수는 배열의 값으로도 사용할 수 있습니다.


var process = [
function(input){ return input + 10;}, // 1 + 1 = 11
function(input){ return input * input;}, // 11 * 11 = 121
function(input){ return input / 2;} // 121 / 2 = 60.5
];
var input = 1;

for(var i = 0; i < process.length; i++){
input = process[i](input);
}

console.log(input); // 60.5


위에서 설명한 것 처럼 함수는 값으로 취급됩니다. 그리고 함수는 객체입니다.

이는 함수도 일반 객체처럼 취급될 수 있다는 것을 말합니다.

때문에 자바스크립트 함수는 다음과 같은 동작이 가능합니다.


1. 함수는 리터럴에 의해 생성된다.

2. 함수는 함수의 인자로 전달이 가능하다.

3. 변수나 배열의 원소, 객체의 프로퍼티 등에 할당이 가능하다.

4. 함수는 함수의 리턴값으로 리턴이 가능하다.

5. 함수는 동적으로 프로퍼티를 생성 및 할당이 가능하다.


이와 같이 앞에서 나열한 기능이 모두 가능한 데이터 타입을 프로그래밍에서는 first-class object(일급객체), first-class citizen, entity 라고 부릅니다.






콜백(callback)

콜백은 함수를 값으로서 사용되는 용도와도 밀접한 관련이 있습니다.

값으로 사용될 수 있는 특성을 이용하면 함수의 인자로 함수를 전달할 수 있습니다.

값으로 전달된 함수는 호출될 수 있기 때문에 이를 이용하면 함수의 동작을 완전히 바꿀 수 있습니다.


다음의 코드는 인자로 전달된 함수 sortNumber 의 구현에 따라서 빌트인 sort 메소드의 동작방법이 완전히 바뀌게 됩니다.


var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];

console.log(numbers.sort()); // [1,10,2,20,3,4,5,6,7,8,9]
// .()앞에 있는 모든 것은 객체라고 봐도 무방하다. 배열은 객체에 속한다.
// 배열객체에는 빌트인 메소드 sort가 있기 때문에 sort 메소드를 사용할 수 있다.

function sortNumber(a,b){
// 위의 예제와 비교해서 a b의 순서를 바꾸면 정렬순서가 반대가 된다.
return b-a;
}

var numbers2 = [20, 10, 9,8,7,6,5,4,3,2,1];

alert(numbers2.sort(sortNumber)); // array, [20,10,9,8,7,6,5,4,3,2,1]


콜백 함수는 주로 함수 내부의 처리 결과값을 함수 외부로 내보낼 때 사용합니다. 일종의 return 문과 비슷한 기능을 한다고 생각해도 됩니다.


콜백 함수를 사용하는 구조는 일반적으로 특정 함수의 매개변수 값으로 콜백 함수를 넘긴 후 처리 결과를 콜백함수의 매개변수에 담아 콜백 함수를 호출하는 구조를 가지고 있습니다.


이러한 구조를 사용하게 되면 로직 구현 구분과 로직 처리 구분을 나눠서 코딩할 수 있게 됩니다.


이에 따라 로직 구현 부분은 동일하지만 로직 처리 부분을 다양하게 처리해야 하는 경우에 유용하게 사용할 수 있습니다.




function calc(option, num1, num2, callback) {
        var result = "";

        switch (option) {
        case "+":
        result = num1 + num2;
        break;
        case "-":
        result = num1 - num2;
        break;
        case "*":
        result = num1 * num2;
        break;
        case "/":
        result = num1 / num2;
        break;

        default:
        result = "올바른 연산자를 사용해주세요.";
        }

        callback(result);
        }

        function println1(result) {
        document.write("두 수의 합은 = " + result + "입니다.", "<br>");
        }

        function println2(result) {
        document.write("정답은 =" + result + "입니다.<br>");
        }

        calc("+", 10, 20, println1);
        calc("+", 10, 20, println2);

See the Pen JYLOKP by jaeheekim (@jaehee) on CodePen.







사용 방법에 따른 함수 종류


 함수 종류

 

일반 함수 

가장 일반적으로 사용되는 함수( 냉무 ㅋ) 

중첩 함수 

함수 안에 함수가 있는 경우를 중첩되어있다라고 하며 이때 함수 안에 있는 함수를 중첩함수라고 합니다. 

콜백 함수 

함수의 실행 결과값을 리턴이 아닌 매개변수로 넘어온 함수를 호출해서 념겨주는 방식을 콜백이라 하며, 이때 매개변수로 넘어온 함수를 콜백 함수라고 합니다. 

클로저 함수 

일반적인 함수의 경우 함수 호출에 의해 함수 내부의 실행구문을 모두 실행하게 되면 함수 내부에서 만든 지역 변수가 자동으로 사라지지만 어떤 경우에는 사라지지 않고 남아있는 경우가 있습니다.

이러한 현상을 클로저라고 하며 이 현상을 일으키는 함수를 클로저 함수라고 합니다. 

멤버 함수(메서드) 

멤버 함수는 클래스 내부에 만들어지며 주로 메서드라고 부릅니다. 




Jaehee's WebClub