JavaScript 2.16

4 minute read

함수 표현식

  • 자바스크립트는 함수를 특별한 종류의 값으로 취급한다.

  • 함수 표현식으로 함수를 생성할 수 있다.

// 함수를 만들고 그 함수를 변수 sayHi에 할당하기
let sayHi = function() {
  alert( "Hello" );
};
  • 함수를 생성하고 변수에 값을 할당하는 것처럼 함수가 변수에 할당된다.

  • 함수는 값이기 때문에 alert를 이용하여 함수 코드를 출력할 수도 있다.

function sayHi() {
  alert( "Hello" );
}

alert( sayHi ); // 함수 코드가 보임
  • sayHi 옆에 괄호가 없기 때문에 함수는 실행되지 않는다.
  • 자바 스크립트는 괄호가 있어야만 함수가 호출된다.
  • 자바 스크립트에서 함수는 값이다. 따라서 함수를 값처럼 취급할 수 있다.
  • 변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있다.
function sayHi() {   // (1) 함수 생성
  alert( "Hello" );
}

let func = sayHi;    // (2) 함수 복사

func(); // Hello     // (3) 복사한 함수를 실행(정상적으로 실행)!
sayHi(); // Hello    //     본래 함수도 정상적으로 실행.
  • 1에서 함수 선언 방식을 이용해 함수를 생성. 생성한 함수는 sayHi라는 변수에 저장.
  • 2에선 sayHI를 새로운 변수 func에 복사. 이때 괄호가 없다는 것에 유의. 괄호가 있었다면 func = sayHi()가 되어 sayHi 가 되어 sayHi 함수 그 자체가 아니라, 함수 호출 결과(함수의 반환 값)가 func에 저장된다.
  • sayHi()와 func()로 함수를 호출할 수 있음
  • sayHi 는 아래와 같이 함수 표현식을 사용해 정의할 수 있다.
let sayHi = function() {
  alert( "Hello" );
};

let func = sayHi;
// ...

세미콜론

  • 함수 표현식의 끝에 왜 세미콜론이 붙는가?
  • 함수 선언문에는 세미콜론이 없다.
function sayHi() {
  // ...
}

let sayHi = function() {
  // ...
};
  • 중괄호로 만든 코드 블록 끝엔 세미콜론이 없어도 된다.
  • 함수 표현식은 let sayHi = …; 과 같은 구문 안에서 값 역할을 한다.
  • 모든 구문의 끝에는 세미콜론을 붙이는 게 좋기 때문에 함수 표현식 끝에 세미콜론을 붙인다.

콜백 함수

  • 함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 나중에 호출하는 것이 콜백 함수의 개념이다.
// 매개변수가 3개 있는 함수 ask(question, yes, no)
// question
// 질문
// yes
// "Yes"라고 답한 경우 실행되는 함수
// no
// "No"라고 답한 경우 실행되는 함수
// 함수는 반드시 질문을 해야하고 사용자의 답변에 따라 yes()나 no()를 호출한다.

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

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

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

// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
  • 위 예시에선 사용자가 yes라고 대답한 경우 showOK가 콜백이 되고 no라고 대답한 경우 showCancel가 콜백된다.

  • 아래와 같이 함수 표현식을 사용하면 코드 길이가 짧아진다.

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

ask(
  "동의하십니까?",
  function() { alert("동의하셨습니다."); },
  function() { alert("취소 버튼을 누르셨습니다."); }
);
  • ask(…) 안에 이름없이 선언한 익명 함수를 사용한다.
  • 익명함수는 ask 바깥에선 접근할 수 없다.

함수는 동작을 나타내는 값이다.

  • 문자열이나 숫자 등의 일반적인 값들은 데이터를 나타낸다.
  • 함수는 하나의 동작을 나타낸다.
  • 동작을 대변하는 값인 함수를 변수 간 전달하고 동작이 필요할 때 이 값을 실행할 수 있다.

함수 표현식 vs 함수 선언문

첫번째 차이 : 문법

  • 함수 선언문 : 함수는 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다.
// 함수 선언문
function sum(a, b) {
  return a + b;
}
  • 함수 표현식 : 함수는 표현식이나 구문 구성 내부에 생성된다. 다음 예시에선 함수가 할당 연산자를 이용해 만든 할당 표현식 우측에 생성되었다.
// 함수 표현식
let sum = function(a, b) {
  return a + b;
};

두번째 차이 : 자바 스크립트 엔진이 언제 함수를 생성하는냐.

  • 함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성한다.
    • 따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있다.
  • 함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있다.
    • 전역 함수 선언문은 스크립트 어디에 있느냐에 상관없이 어디서든 사용할 수 있다.
    • 자바스크립트는 스크립트를 실행하기 전, 준비 단계에서 전역에 선언된 함수 선언문을 찾고, 해당 함수를 생성한다. 스크립트가 진짜 실행되기 전 초기화 단계에서 함수 선언 방식으로 정의한 함수가 생성된다.

세번째 차이 : 스코프

  • 엄격 모드에서 함수 선언문이 코드 블록 내에 뒤치하면 해당 함수는 블록 내 어디서든 접근할 수 있다.
  • 하지만 블록 밖에서는 함수에 접근하지 못한다.
// 예시1
let age = prompt("나이를 알려주세요.", 18);

// 조건에 따라 함수를 선언함
if (age < 18) {

  function welcome() {
    alert("안녕!");
  }

} else {

  function welcome() {
    alert("안녕하세요!");
  }

}

// 함수를 나중에 호출합니다.
welcome(); // Error: welcome is not defined


// 예시2
let age = 16; // 16을 저장했다 가정합시다.

if (age < 18) {
  welcome();               // \   (실행)
                           //  |
  function welcome() {     //  |
    alert("안녕!");        //  |  함수 선언문은 함수가 선언된 블록 내
  }                        //  |  어디에서든 유효합니다
                           //  |
  welcome();               // /   (실행)

} else {

  function welcome() {
    alert("안녕하세요!");
  }
}

// 여기는 중괄호 밖이기 때문에
// 중괄호 안에서 선언한 함수 선언문은 호출할 수 없습니다.

welcome(); // Error: welcome is not defined
  • 함수 선언문은 함수가 선언된 코드 블록 안에서만 유효하기 때문에 에러가 발생한다.

  • if 문 밖에서 welcome 함수를 호출하기 위해선 함수 표현식을 사용하면 된다.

let age = prompt("나이를 알려주세요.", 18);

let welcome;

if (age < 18) {

  welcome = function() {
    alert("안녕!");
  };

} else {

  welcome = function() {
    alert("안녕하세요!");
  };

}

welcome(); // 제대로 동작합니다.


// ? 연산자 사용 시 코드 간략화 가능
let age = prompt("나이를 알려주세요.", 18);

let welcome = (age < 18) ?
  function() { alert("안녕!"); } :
  function() { alert("안녕하세요!"); };

welcome(); // 제대로 동작합니다.
  • 함수 선언문과 함수 표현식 중 무엇을 선택해야 하는가?
    • 함수 선언문을 이용해 함수를 선언하는 것을 먼저 고려하는 것이 좋다.
    • 함수가 선언되기 전에 호출할 수 있어서 코드 구성을 좀 더 자유롭게 할 수 있다.

Categories:

Updated: