12장. 함수

29465 단어 JavaScriptJavaScript

* 함수는 자바스크립트에서 가장 중요한 핵심!!

자바스크립트의 핵심 개념

  함수, 스코프, 실행 컨텍스트, 클로저, 생성자 함수에 의한 객체 생성, 메서드, this, 프로토타입, 모듈화 ....

  • 함수란?

    --> 입력을 받아 출력을 내보내는 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것

    함수의 구성요소

    1) 매개변수: 함수 내부로 입력을 전달받는 변수
    2) 인수: 입력
    3) 반환값: 출력

    함수 정의

    function add(x+y) { //x,y는 매개변수
     return x + y
    }

    --> 함수의 정의만으로 함수가 실행되는 것은 아니다.
    --> 인수를 매개변수를 통해 함수에 전달하면서 함수의 실행을 명시적으로 지시해야 함. -> 함수 호출

    var result = add(2,5); // 2,5는 인수
    console.log(result); // 7
  • 함수를 사용하는 이유

    --> 필요할 때 여러 번 호출 가능 (실행 시점 결정, 코드의 재사용)
    --> 유지보수의 편의성, 코드의 신뢰성 상승
    * 함수는 객체 타입의 값이다. -> 식별자를 붙일 수 있음.

  • 함수 리터럴

    --> 함수는 객체 타입의 값이므로 함수 리터럴로 생성할 수 있다.
    --> 리터럴은 값을 생성하기 위한 표기법
    함수는 객체다!!! 일반 객체와는 달리 함수 객체는 호출할 수 있다.

    var f = function add(x,y) {
     return x + y;
    }; // 변수에 함수 리터럴을 할당

    함수 리터럴의 구성 요소

    1) 함수 이름: 식별자, 생략 가능(무명, 익명 함수)
    2) 매개변수 목록: 함수 몸체 내에서 변수와 동일하게 취급
    3) 함수 몸체: 함수 호출에 의해 실행

  • 함수 정의

    함수 정의 방식

    1) 함수 선언문
    2) 함수 표현식
    3) Function 생성자 함수
    4) 화살표 함수(ES6)

    1. 함수 선언문: 표현식이 아닌 문

    function add(x, y) {
    return x + y;
    }

    함수 리터럴과 함수 선언문은 형태가 동일하지만 다르다!
    --> 함수 선언문은 함수명을 생략할 수 없다.
    --> 함수 선언문은 표현식이 아닌 문이다. (값으로 평가 x)
    함수 리터럴: 호출 불가능, 함수를 가리키는 식별자가 없음
    함수 선언문: 호출 가능, 자바스크립트 엔진이 암묵적으로 식별자 생성
     함수는 함수 이름으로 호출하는 것이 아닌 함수 객체를 가리키는 식별자로 호출한다.

    2. 함수 표현식: 표현식인 문

    자바스크립트의 함수는 일급 객체이다.
    --> 함수를 값처럼 자유롭게 사용할 수 있다.
    --> 함수 리터럴로 생성한 함수 객체를 변수에 할당 가능

    var add = function (x, y) { // 함수 리터럴은 함수명 생략 가능
    return x + y;
    };
    console.log(add(2,5)); // 7, 함수명이 아닌 함수 객체를 가리키는 식별자로 호출

    * 함수 생성 시점과 함수 호이스팅

      함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르다.
    함수 선언문: 런타임 이전에 먼저 실행 -> 함수 호이스팅
    함수 표현식: 변수 호이스팅과 동일하게 동작

    함수 호이스팅 vs 변수 호이스팅

     함수 호이스팅: 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화
     변수 호이스팅: undefined로 초기화, 변수 할당문의 값은 런타임에 평가

    --> 함수 선언문 대신 함수 표현식을 사용하자. (함수 호이스팅은 시점을 무시한다.)

    3. Function 생성자 함수

    --> new 연산자와 함께 호출하면 함수 객체를 생성해서 반환

    var add = new Function('x', 'y', 'return x + y');
    console.log(add(2,5)) // 7

    생성자 함수로 함수를 생성하는 방식은 바람직하지 않다.

    4. 화살표 함수 (ES6)

    --> 화살표 함수는 항상 익명 함수로 정의

    const add = (x,y) => x + y;
    console.log(add(2,5)); // 7
  • 함수 호출

    1. 매개변수와 인수

    --> 함수를 실행하기 위해 필요한 값을 매개변수를 통해 인수를 함수 내부로 전달한다.
    * 매개변수: 함수를 정의할 때 선언, 함수 내부에서 변수와 동일하게 취급
    --> 매개변수의 스코프는 함수 내부이다.

    2. 인수 확인

    1) 자바스크립트 함수는 매개변수와 인수의 개수가 일치하는지 확인 x
    2) 자바스크립트 함수는 매개변수의 타입을 사전에 지정 x
    * 해결책 1. 적절한 인수가 전달되었는지 확인 장치

    function add(x, y) {
      if (typeof x !== 'number' || typeof y !== 'number') {
          throw new TypeError('인수는 모두 숫자 값이어야 합니다.');
      }
      return x + y;
    };

    * 해결책 2. 단축 평가로 매개변수에 기본값 할당

     function add(a,b,c) {
         a = a || 0;
         b = b || 0;
         c = c || 0;
         return a + b + c;
     }
     console.log(add(1,2)); // 3
     console.log(add(1)); // 1
     console.log(add()); // 0

    * 해결책3. 매개 변수에 기본값 사용 (ES6)

    function add(a = 0, b = 0, c = 0) {
     return a + b + c;
    }

    3. 매개변수의 최대 개수

    --> 3개 이상을 넘기지 말자!!

    4. 반환문 (return)

    function multiply(x, y) {
      return x * y; // 반환문
    }
    var result = multiply(3, 5); // 함수 호출은 반환값으로 평가
    console.log(result); // 15

    반환문의 기능
    1) 함수의 실행을 중단하고 함수 몸체를 빠져나온다. (반환문 이후의 문은 무시)
    2) 반환문은 return 키워드 뒤에 오는 표현식을 평가해 반환 (지정되있지 않으면 undefined 반환)
    --> 반환문은 함수 내부에서만 사용 가능

  • 참조에 의한 전달과 외부 상태의 변경

    1) 원시 값: 에 의한 전달
    2) 객체: 참조에 의한 전달
    --> 매개변수도 타입에 따라 값, 참조에 의한 전달 방식을 따른다. 부수효과 발생

    function changeVal(primitive, obj) { // 첫 번째 매개변수는 원시 값, 두 번째 매개변수는 객체를 전달받음.
       primitive += 100;
       obj.name = 'Kim';
    }
    // 외부 상태
    var num = 100;
    var person = {name: 'Lee'};
    console.log(num); // 100
    console.log(person); // {name: 'Lee'}
    changeVal(num, person);
    console.log(num); // 100 -> 원본 훼손 x
    console.log(person); // {name: 'Kim'} -> 원본 훼손
  • 다양한 함수의 형태

    1. 즉시 실행 함수

    --> 함수 정의와 동시에 즉시 호출되는 함수, 단 한 번만 호출되며, 다시 호출이 불가능하다.
    --> 일반적으로 익명 함수를 사용한다.

    (function () { // 익명 즉시 실행 함수
        var a = 3;
        var b = 5;
        return a * b;
    }());

    --> 일반 함수처럼 값 반환과 인수 전달이 가능하다.
    1) 값 반환

    var res = (function () {
      var a = 3;
      var b = 5;
      return a * b;
    }());
    console.log(res); // 15

    2) 인수 전달

    res = (function (a,b) {
    return a * b;
    }(3, 5));
    console.log(res); // 15

    2. 재귀 함수

    --> 자기 자신을 호출하는 함수 (반복문의 역할을 수행할 수 있다.)
    --> 재귀 함수는 무한 재귀 호출하므로, 반드시 탈출 조건을 만들어야 한다.
    --> 재귀 함수는 반복문보다 직관적으로 이해하기 쉬울 때만 사용하자.
    1) 반복문

    function countdown(n) {
      for (var i = n; i >= 0; i--) console.log(i);
    }

    2) 재귀 함수

    function countdown(n) {
      if (n < 0) return; // 탈출 조건
      console.log(n);
      countdown(n-1);
    }

    재귀 함수: 팩토리얼

    function factorial(n) {
      if (n <= 1) return 1; // 탈출 조건
      return n * factorial(n-1);
    }

    함수 호출은 함수명이 아닌 함수를 가리키는 식별자명으로 호출한다!!

    3. 중첩 함수 (내부 함수)

    --> 함수 내부에 정의된 함수
    --> 중첩 함수는 외부 함수 내부에서만 호출 가능, 헬퍼 함수의 역할

    function outer() { // 외부 함수
      var x = 1;
      function inner() {
          var y = 2;
          console.log(x + y); // 외부 함수의 변수 참조 가능
      }
      inner();
    }
    outer();

    4. 콜백 함수: 배열에서의 활용도가 아주 높다!!

    function repeat(n, f) {
     for (var i = 0; i < n; i++) {
         f(i);
     }
    }
    var logAll = function (i) {
    console.log(i);
    }
    var logOdds = function (i) {
    if (i % 2) console.log(i);
    };
    repeat(5, logAll); // 0 1 2 3 4
    repeat(5, logOdds); // 1 3

    콜백함수: 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
    --> 콜백함수는 고차함수의 헬퍼함수 역할을 한다.
    고차함수: 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수

    5. 순수 함수와 비순수 함수

    1) 순수 함수: 어떤 외부 상태에 의존하지도 않고 변경하지도 않는, 부수 효과가 없는 함수
    2) 비순수 함수: 외부 상태에 의존하거나 외부 상태를 변경하는, 부수 효과가 있는 함수

좋은 웹페이지 즐겨찾기