자바스크립트 기본 - 함수 표현식

devheyrin·2022년 4월 20일
0

modern javascript

목록 보기
16/26

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

다른 언어에서는 함수를 ‘특별한 동작을 하는 구조'로 취급하는 것과 차이가 있다.

함수 선언 방식이 아닌 함수 표현식으로도 함수를 만들 수 있다.

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

함수 생성 방식에 관계 없이 함수는 값이고, 따라서 변수에 할당할 수 있다. 함수는 값이기 때문에 alert() 로 출력하면 함수 코드가 출력된다.

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

alert( sayHi ); // 함수 코드가 보임

sayHi() 처럼 괄호를 붙여주면 함수를 실행할 수 있고, sayHi 처럼 괄호가 없다면 함수 코드가 문자형으로 바뀌어 출력된다. 자바스크립트에서는 괄호가 있어야만 함수가 호출된다!

함수의 본질은 값이기 때문에 변수를 복사해 다른 변수에 복사하는 일도 할 수 있다.

function sayHi() {   // (1) 함수 생성
  alert( "Hello" );
}

// (1) - 1 함수 표현식으로 함수 생성 
let sayHi = function() {
  alert( "Hello" );
};

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

copiedSayHi(); // Hello     // (3) 복사한 함수를 실행
sayHi(); // Hello    // 본래 함수도 정상적으로 실행

주의해야 할 점이 있는데, (2) 에서 sayHi() 처럼 괄호를 붙여 변수에 할당했다면 함수가 실행된 후 호출 결과(반환값)이 왼쪽 변수에 할당되어 copiedSayHi 는 undefined 가 되었을 것이다.

괄호를 붙이지 않고 할당했기 때문에 함수를 복사해 줄 수 있다.

💡 함수 표현식 끝의 세미콜론
함수 표현식 끝에는 세미 콜론을 적어주어야 하지만, 함수 선언문에는 세미콜론을 붙이지 않아도 된다. if, for, function 과 같이 중괄호로 만든 코드 블록 끝에는 세미콜론이 없어도 된다. 함수 표현식은 코드 블록이 아닌 값처럼 취급되어 변수에 할당된다. 모든 구문의 끝에는 세미 콜론을 붙이는 것이 바람직하기 때문에, 함수 표현식이라는 구문의 끝에도 세미콜론을 붙여 주는 것이다.

콜백 함수

아래 코드에서 ask() 라는 함수의 매개변수로는 question, yes, no 가 있다.

question - 질문

yes - Yes 라고 답한 경우 실행되는 함수

no - No 라고 답한 경우 실행되는 함수

함수는 반드시 question 을 해야 하고, 사용자의 답변에 따라 yes() 나 no() 함수를 호출한다.

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
// confirm 창에서 '확인'을 누르면 yes 함수가 실행된다. 
}

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

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

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

위 코드에서 ask 의 인수인 showOk 와 showCancel 은 콜백 함수 또는 콜백 이라고 한다.

콜백 함수란 함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 나중에 호출(called back) 하는 것이 콜백 함수의 개념이다.

함수 표현식을 사용하면 같은 코드를 좀 더 짧게 작성할 수 있다.

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

ask(
  "동의하십니까?",
  function() { alert("동의하셨습니다."); },
  function() { alert("취소 버튼을 누르셨습니다."); }
);

ask 함수 안에 이름 없는 함수를 생성해 인자로 넣어주었다. 이렇게 이름 없이 선언한 함수를 익명 함수라고 한다. 익명 함수는 ask 바깥에서는 접근할 수 없다.

💡 자바스크립트에서 함수는 **‘동작'**을 나타내는 **‘값'**이다.

함수 표현식 vs 함수 선언문

함수 표현식과 선언문의 차이를 알아보자!

  1. 문법
    • 함수 선언문 : 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다.
      function sum(a, b) {
        return a + b;
      }
    • 함수 표현식 : 표현식이나 구문 구성 내부에 함수가 생성된다.
      let sum = function(a, b) {
        return a + b;
      };
  2. 자바스크립트 엔진의 함수 생성 시점
    • 함수 표현식 : 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성한다. 따라서 실행 흐름이 함수에 도달했을 때부터 함수를 사용할 수 있다. 아래 코드에서는 함수 표현식으로 함수를 생성했는데, sayHi 함수를 생성하기 전에 호출하려 했기 때문에 에러가 발생한다.
      sayHi("John"); // error!
      
      let sayHi = function(name) { 
        alert( `Hello, ${name}` );
      };
    • 함수 선언문 : 함수 선언문이 정의되기 전에도 호출할 수 있다. 따라서 전역 함수 선언문은 스크립트 어디서든 사용할 수 있다. 아래 코드에서는 sayHi 함수 선언 이전에 함수를 호출했지만, 전역 함수 선언문으로 함수가 생성되었으므로 어디에서든 함수를 호출할 수 있다.
      sayHi("John"); // Hello, John
      
      function sayHi(name) {
        alert( `Hello, ${name}` );
      }
    • 자바스크립트는 스크립트가 실행되기 전 ‘초기화 단계'에서 함수 선언 방식으로 정의한 함수를 생성한다. 스크립트는 함수 선언문이 모두 처리된 이후 실행되므로 어디에서든 함수에 접근할 수 있는 것이다.
  3. 스코프
    • 함수 선언문 : 엄격 모드일 때, 함수 선언문이 코드 블록 내에 위치하면 블록 내에서는 어디서든 해당 함수에 접근할 수 있다. 하지만 블록 밖에서는 블록 내에 선언된 함수에 접근할 수 없다. 따라서 아래 코드는 에러가 발생한다.
      let age = prompt("나이를 알려주세요.", 18);
      
      // 조건에 따라 함수를 선언함
      if (age < 18) {
      	welcome();
        function welcome() {
          alert("안녕!");
        }
      } else {
      	welcome();
        function welcome() {
          alert("안녕하세요!");
        }
      	welcome();
      }
      
      // 함수를 나중에 호출합니다.
      welcome(); // Error: welcome is not defined
    • 함수 표현식 : 함수 표현식을 사용하면 코드 블록 밖에서도 함수를 호출할 수 있다. 코드 블록 밖에 변수를 선언해 둔 다음, 코드 블록 내에서 함수를 할당한 후 다시 코드 블록 밖에서 함수를 호출하면 된다.
      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(); // 제대로 동작합니다.
💡 함수 선언문과 표현식 중 무엇을 선택해야 할까?
함수 선언문을 먼저 고려하는 것이 좋다. 함수 선언문으로 함수를 정의하면 선언 이전에 호출할 수 있어서 코드 구성이 좀더 자유로워지기 때문이다. 함수 선언문을 사용하는 것이 가독성에서도 좀더 좋다. 함수 선언 방식이 적합하지 않거나, 조건에 따라 함수를 선언해야 하는 경우 함수 표현식을 사용해야 한다.
profile
개발자 헤이린 🔜 프로덕트 매니저로 나아가는 중!

0개의 댓글