[자바스크립트 딥다이브] 12장 함수

seoyeon·2024년 1월 5일
0

함수

1) 함수란

: 일련의 과정을 으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의 한것

함수를 사용하는 이유는?

  • 유지보수의 편이성↑
  • 코드의 신뢰성
  • 코드의 가독성

**함수 리터럴**
  • 리터럴이란 : 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기 방식
    • 함수는 호출할 수 있는 객체이다 => 함수 리터럴이 값을 생성하고, 이 값은 객체
  • 구성요소
    • 함수 이름 (식별자) => 기명함수, 무명/익명 함수가 있다
    • 매개변수 목록
    • 함수 몸체

**함수는 일급객체** => 값의 성질을 지님
  • 변수에 할당(assignment)할 수 있다.
  • 다른 함수를 인자(argument)로 전달 받는다.
  • 다른 함수의 결과로서 리턴될 수 있다.

2) 함수 정의

변수는 '선언', 함수는 '정의'로 표현한다

2-1. 함수 선언문

함수선언문은 표현식(값을 반환하는 식/코드)이 아닌 문(프로그래밍을 실행하는 최소단위)

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

var sum = function sum(x, y){ // 의사코드
    return x+y;
}
  • 함수 이름을 생략할 수 없다

    • 자바스크립트 엔진은 함수를 호출하기 위해 함수이름과 동일한 식별자를 생성하고,
      함수 객체(참조값)를 할당한다.
      => 함수는 함수객체를 가리키는 식별자로 호출되는것 (함수이름X)
  • 함수 선언문은 변수에 할당할 수 없다

    var sayHi = function sayHi(){
        return 'hi';
    }
    • 다음 코드가 동작하는 이유는? 자바스크립트 엔진이 function sayHi를 함수 선언문이 아닌 함수 리터럴 표현식으로 해석했기 때문
  • 함수 선언문을 피연산자로 사용하면 함수 리터럴 표현식으로 해석됨

    (function sayHi(){ console.log('hi'); }); // 함수 리터럴 표현식(이름 생략 가능)
    sayHi(); // sayHi is no defined

> 결론 : 기명함수 리터럴은 코드 문맥에 따라 **함수선언문** 또는 **함수 리터럴 표현식**으로 해석될수 있다
### 2-2. 함수 표현식

함수리터럴로 생성한 함수 객체를 변수에 할당하는 정의방식

var sum = function (x, y){
    return x+y;
}
  • 익명함수 (함수명 생략 가능)
  • 함수 리터럴이 기명함수여도 함수 이름은 반드시 식별자!

호이스팅(함수 선언문 vs 함수 표현식)

호이스팅이란 : js 엔진이 코드가 실행하기 전 변수선언/함수선언이 해당 스코프의 최상단으로 끌어 올려진 것처럼 보이는 현상

  • 변수 호이스팅 : var 키워드로 선언된 변수는 undefined로 초기화
  • 함수 호이스팅 : 함수 객체로 초기화
    함수 표현식은 변수 호이스팅 발생 (런타임 이전에 undefined로 초기화 / 런타임 때 함수 객체가 됨)
    함수표현식 ; 변수에 할당 되는 값이 함수 리터럴인 문 -> 변수로 인식한다

2-3. 함수 생성자

객체를 생성하는 함수

var sum = new Function('age', 'height', 'return age + height')
  • 문자열을 이용해 함수를 만들어야할 때도 사용한다

2-4. 화살표 함수

const sum = (age, height) => age + height;
  • ES6에서 도입된 화살표 함수는 간략한 방법으로 함수선언 가능

화살표 함수의 한계

  • 생성자 함수로 사용 X
  • this 바인딩 방식이 다름
  • 프로토타입 프로퍼티 X
  • argument객체를 생성하지 않는다

3) 함수 호출

3-1. 매개변수 & 인수

  • 인수는 반드시 표현식이어야함

  • 매개변수가 undefined로 초기화 된 후 인수가 순서대로 할당 된다

  • 매개변수 > 인수 개수 => 할당되지 않은 매개변수 값은 undefined로 할당됨
    매개변수 < 인수 개수 => 초과된 인수는 암묵적으로 arguments 객체의 프로퍼티로 보관

    function add(a, b){
       return a + b;
    }
    add(1);
    add(1, 2, 3);
  • 인수가 전달되지 않은 경우 단축평가 혹은 default값으로 기본값 부여

    function test(a, b = 0){
        a = a || 0; // a값이 없으면 0할당
    }

* 매개변수는 최대 3개 이상 넘지 않는것을 권장

이상적인 함수는 한 가지 일만 해야 하며 가급적 작게 만들어야 한다. 172p


### 3-2. 반환문
  • 함수 호출 표현식 => 반환값
  • 역할
    • 함수의 실행을 중단
    • return 키워드 뒤 표현식 반환 (생략할 경우 undefined 반환)

3-3. 참조에 의한 외부 상태 변경

function change(num, obj) {
    num += 1;
    obj.age = 10
}
var age = 12;
var student = { age : 12 }

change(age, student);
console.log(age, student); // 12, 10 -> 객체는 원본 훼손
  • 원시값 ->값에 의한 전달이 되어 원본 값이 변경되지 않음
  • 참조값 -> 참조에 의한 전달이 되어 원본이 변경됨
    • 객체의 변경 추적이 필요한 경우 옵저버 패턴 등을 통해 추가 대응이 필요함
    • 깊은 복사를 통해 불변객체를 만들자
    • 순수함수(외부 상태에 의족하지 않는 함수)로 안정성을 높이는 함수형 프로그래밍 지향

4) 함수의 다양한 형태~

4-1. 즉시 실행 함수

(function() {
    alert('hi'); 
}());
  • 익명함수 사용, 기명함수는 즉시 실행 함수를 호출할 수 없다

4-2. 재귀 함수

재귀 호출(자기 자신을 호출하는 행위)을 수행하는 함수

var factorial = function a(n){
    if (n <= 1) return 1;
    return n * factorial(n - 1);
};
factorial(5);

4-3. 콜백 함수

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수

function repeat(n, f){    // f는 고차 함수
    for(var i=0; i<n; i++){
        f(i)
    }
}

var logOdds = function(i) {
    if (i % 2 ) console.log(i);
};
repeat(5, logOdds);    // logOdds는 콜백함수
  • 배열 고차 함수에서도 사용

    var res = [1,2].map(function (item) { return item*2;});

4-4. 순수 함수 vs 비순수 함수

  • 순수 함수 : 부수효과가 없는 함수
    • 부수 효과 : 외부 상태에 의존하거나 외부 상태를 변경하는 효과
    • 일반적으로 최소 하나 이상의 인수를 전달받음 - 불변성 유지
  • 비순수 함수 : 부수효과가 있는 함수
var count = 0;

function pureFunc(n){    // 순수 함수
    return ++n;
}

function impureFunc(){    // 비순수 함수
    return ++count;
}

count = pureFunc(count);
impureFunc();
  • 순수 함수 -> 순수 함수가 반환한 결과값을 변수에 재할당하여 상태 변경
  • 비순수 함수 -> 외부 상태에 의존하여 상태 변경 => 상태 변화를 추적하기 어려움
profile
항상 질문하는 개발자가 되고 싶습니다✋

0개의 댓글