본문 바로가기
공부/JavaScript

Function

by 무심한고라니 2020. 12. 26.

자바스크립트의 핵심 개념인 함수를 정리하고자 글을 남깁니다. 참고한 자료들은 최하단에 기재하였고, 글의 대략적인 목차는 다음과 같습니다.

 

1. 유효범위(Scope)

2. 정의

3. 함수 표현식 vs. 함수 선언식

 

_____

 

유효범위(Scope)

 

자바스크립트에서 함수란 어떤 작업을 수행하기 위해 필요한 문(statement)들의 집합을 정의한 코드 블록이다. 이는 코드의 재사용 측면에서 유용하다는 점에서 타언어와 같지만 자바스크립트의 함수는 조금 특별하다.

 

var globalNum = 10;	// globalNum을 전역 변수로 선언함.
function printNum() {	// 함수 선언문
    document.write("지역 변수 globalNum 선언 전의 globalNum의 값은 " + globalNum + "이다.<br>"); // ①
    var globalNum = 20; // globalNum을 지역 변수로 선언함. // ②
    document.write("지역 변수 globalNum 선언 후의 globalNum의 값은 " + globalNum + "이다.<br>");
}
printNum();

 

일반적인 언어라면 블록 단위의 유효 범위를 가진다[1]. 즉 블록 내에서 정의된 변수를 블록 외부에서는 접근할 수 없다[2]. 하지만 자바스크립트는 다른 언어와 달리 함수를 블록 대신 사용한다. 따라서 위 코드 실행 시 브라우저에 찍히는 globalNum 값은 차례대로 undefined, 20이다. ①의 시점에서 변수 globalNum이 전역 변수를 가리킨다고 생각하기 쉽지만 자바스크립트의 변수는 함수 단위로 호이스팅[4]되기 때문이다[3].

 

정의

 

한편 자바스크립트의 기본적 구성 블록인 함수는 총 세 가지 방법으로 정의할 수 있습니다.

 

1. 함수 선언문(Function declaration)

2. 함수 표현식(Function expression)

3. Function 생성자 함수

 

먼저 위 예에도 언급되었지만 함수 선언문은 아래와 같이 함수를 정의한다.

 

/*
 * 1. 함수명: 함수 선언문의 경우, 함수명은 생략할 수 없다.
 *           함수명은 함수 몸체에서 재귀적 호출(Recursive function call)하거나 자바스크립트 디버거가 해당 함수를 구분할 수 있도록 식별자의 역할을 한다.
 * 2. 매개변수 목록: 타 언어와의 차이점은 매개변수 타입을 기술하지 않는 것인데, 이로 인해 몸체 내에서 매개변수의 타입 체크가 필요할 수도 있다.
 * 3. 함수 몸체: return문으로 결과값을 반환할 수 있고, 생략시 undefined를 반환한다. 반환의 목적뿐 아니라 함수 종료의 목적으로 사용할 수도 있다(이 경우도 undefined 반환).
 */
function square(number) {
    return number * number;
}

 

즉, 함수 선언은 문(statement)이지만, 함수 표현식에 의해 아래와 같이 정의할 수도 있다[5].

 

var square = function(number) {	// 익명 함수 표현식(anonymous function expression)
    return number * number;
};

 

이 중 어떤 방법을 사용하든 아래와 같이 호출할 수 잇다.

 

square(4);

 

앞서 함수 표현식을 통해 정의한 함수 호출 시 함수명이 아닌 함수를 가리키는 변수명을 사용했다. 함수 선언문 역시 함수명으로 호출되는 것처럼 보이지만 사실은 변수명으로 호출된 것이다. 예로 위에서 함수 선언문으로 정의한 square 함수의 경우, 자바스크립트 엔진에 의해 아래와 같은 함수 표현식 형태로 변경된다.

 

// 함수명과 함수 참조값을 가진 변수명이 일치하므로 함수명으로 호출되는 듯 보이지만 사실은 변수명으로 호출된 것이다.
var square = function square(number) {
    return number * number;
};

 

그렇다면 Function 생성자 함수는 무엇일까? 함수 선언문과 함수 표현식은 모두 함수 리터럴 방식으로 함수를 정의하는데 이것은 결국 내장함수 Function 생성자 함수로 함수를 생성하는 것을 단순화시킨 short-hand 축약법이다. 자세한 내용은 다음(Function() constructor)을 참고한다.

 

함수 표현식 vs. 함수 선언식

 

다음 게시글의 각주7을 참고한다.

 

 

_____

1. 블록이란 코드 내에서 중괄호({})로 둘러싸인 부분을 가리킨다. for문, if문 등을 예로 들 수 있다.

2. 자바스크립트는 블록 내에서 정의된 변수를 블록 외부에서 접근할 수 있다.

var a = 1;
{
    var b = 2;
    console.log("블록 내부: " + a);
    console.log("블록 내부: " + b);
}
console.log("블록 외부: " + a);
console.log("블록 외부: " + b);

// 블록 내부: 1
// 블록 내부: 2
// 블록 외부: 1
// 블록 외부: 2

3. 호이스팅 후의 코드는 다음과 같다.

var globalNum = 10;
function printNum() {
    var globalNum; // 함수 호이스팅에 의해 변수의 선언 부분이 함수의 맨 처음 부분으로 이동됨.
    document.write("지역 변수 globalNum 선언 전의 globalNum의 값은 " + globalNum + "이다.<br>");
    globalNum = 20;
    document.write("지역 변수 globalNum 선언 후의 globalNum의 값은 " + globalNum + "이다.<br>");
}
printNum();

4. 호이스팅(Hoisting)이란 var 선언문이나 function 선언문 등 모든 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다. 자바스크립트는 ES6의 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.

5. 자바스크립트에서 함수 표현식으로 함수를 정의할 수 있는 이유는 함수가 일급 객체[6]로 변수에 할당할 수 있기 때문이다. 이때 변수에는 함수명이 아닌 할당된 함수를 가리키는 참조값이 저장된다. 따라서 함수 호출 시 함수명이 아닌 함수를 가리키는 변수명을 사용해야 한다.

// 기명 함수 표현식(named function expression)
var foo = function multiply(a, b) {
    return a * b;
};

// 익명 함수 표현식(anonymous function expression)
var bar = function(a, b) {
    return a * b;
};

console.log(foo(10, 5));	// 50
console.log(multiply(10, 5));	// Uncaught ReferenceError: multiply is not defined

var bar = foo;

console.log(foo(10, 10)); // 100
console.log(bar(10, 10)); // 100

6. 자바스크립트에서 함수는 값이다. 호출할 수 있다는 점 때문에 일반적인 값과는 조금 다를 수 있지만, 그 본질은 값이므로 값에 할 수 있는 일을 함수에도 할 수 있다. 예로 아래와 같은 콜백 함수[7]를 들 수 있다.

function ask(question, yes, no) {
    if (confirm(question)) yes()
    else no();
}

function showOk() {
    alert( "동의하셨습니다." );
}

function showCancel() {
    alert( "취소 버튼을 누르셨습니다." );
}

// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);

7. 함수 ask의 인수, showOk와 showCancel은 콜백 함수 또는 콜백이라고 불린다. 함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 "나중에 호출(called back)"하는 것이 콜백 함수의 개념이다.

 

_____

참고자료

 

'공부 > JavaScript' 카테고리의 다른 글

비동기 처리  (0) 2020.12.27
느슨한 연결  (0) 2020.12.27
Logical Operators  (0) 2020.12.25
번역] 7가지 유용한 자바스크립트 내장 함수  (0) 2020.12.20
번역] 15가지 자바스크립트 팁  (0) 2020.12.20

댓글