12장 함수(1)

hyewon ji·2023년 2월 10일

1. 함수란?

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

// 함수의 정의
function add(x, y) {
	return x + y;
}

// 함수의 호출
add(2, 5)
  • 함수이름: add
  • 매개변수: x, y
  • 반환값: x + y
  • 인수: 2, 5

2. 함수를 사용하는 이유

함수를 사용하게 되면, 실행시점을 개발자가 결정할 수 있고 코드의 재사용성을 높힌다. 따라서 유지보수성이 좋아지고, 잘 작성하면 코드의 가독성을 향상시킬 수 있다.

3. 함수 리터럴

함수 리터럴은 function 키워드, 함수 이름, 매개 변수 목록, 함수 몸체로 구성된다.

function add(x + y){
  return x + y;
}
  1. 함수이름
    • 식별자로, 식별자 네이밍 규칙을 준수해야 한다.
    • 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자다.
    • 생략 가능하다. (이름 있는 함수는 기명 함수, 이름 없는 함수는 무명/익명 함수이다.)
  2. 매개변수 목록
    • 0개 이상의 매개변수를 소괄호로 감싸고 소괄호로 구분한다.
    • 함수를 호출할 때 지정한 인수가 매개변수에 순서대로 할당된다.
    • 매개변수는 함수 내에서 변수와 동일하게 취급된다. 따라서 식별자 네이밍 규칙을 준수해야한다.
  3. 함수 몸체
    • 함수 호출시 실행될 문을 하나의 실행단위로 정의한 코드 블록이다.
    • 함수 호출에 의해 실행된다.

함수는 객체이며, 일반 객체와 달리 호출이 가능하고 함수 객체만의 고유 프로퍼티를 갖는다.

4. 함수 정의 방법

함수 정의 방법은 4가지가 있다. 차례로 살펴보자

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

1. 함수 선언문

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

함수 선언문은 함수리터럴과 형태가 동일하다. 단, 함수 리터럴은 함수 이름을 생략할 수 있으나 함수 선언문은 함수 이름을 생략할 수 없다. 또한 표현식이 아니므로 변수에 할달할 수 없다.

문맥에 따라 함수 리터럴 혹은 함수 선언문으로 해석이 되는데 단독으로사용하는 경우는 함수 선언문으로 해석하고, 값으로 평가되어야 하는경우는 함수 리터럴로 해석된다.

function foo() { console.log('foo'); }   // 선언문으로 해석
(function bar() { console.log('bar') }); // 리터럴으로 해석

foo(); // foo
bar(); // ReferenceeError: bar is not defined

위 코드에서 리터럴로 생성된 함수 bar가 호출되지 않는 이유가 뭘까? 함수 이름은 함수 몸체 내에서만 참조할 수 있기 때문이다.

그렇다면 선언문으로 생성한 함수 foo는 왜 호출이 가능할까? 이유는 Javascript 엔진이 함수 선언문을 해석할때 함수 이름과 동일한 이름의 식별자를 암묵저으로 생성해 함수객체를 할당하기 때문이다.

즉, 함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다.

2. 함수 표현식

자바스크립트의 함수는 일급객체로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있다. 이때 변수는 함수 객체의 식별자가 되고, 함수의 이름은 일반적으로 생략한다.

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

add(2, 5) // 7

일급 객체 : 값처럼 변수에 할당할 수 있고, 프로퍼티의 값이 될 수있으며, 배열의 요소가 될 수있는 객체

3. Function 생성자 함수

new 연산자와 함께 자바스크립트 빌트인 함수 Function를 호출하면 함수객체가 생성된다.(new 연산자 없이 호출해도 결과는 동일하다)

const add = new Function('x', 'y', 'return x + y')

add(2, 5) // 7

Function 생성자 함수로 함수 생성 방법은 클로저를 생성하지 않고, 함수 선언문 혹은 함수 표현식으로 생성한 함수와 다르게 동작해 권장하지 않는 방법이다.

4. 화살표 함수

ES6에서 도입된 방법으로, 항사 익명으로 정의하며 표현과 내부 동작이 간략화 되어있다.

const add = (x, y) => x + y

add(2, 5) // 7

화살표 함수는 생성자 함수로 사용할 수 없으며, 기존 함수와 this 바인딩 방식이 다르고, prototype의 프로퍼티가 없으며 arguments 객체를 생성하지 않는다.

5. 함수의 호출

함수는 함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출한다.

1. 매개변수와 인수

함수가 호출되면 함수 몸체에 암묵적으로 매개 변수가 생성되고 undefined로 초기화된후, 인수가 순서대로 할당된다. 이때, 인수는 값으로 평가될 수 있는 표현식이여야 한다. 매개 변수보다 인수의 개수가 작아 할당되지 않은 매개변수는 undefined이다.

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

add(2) // NaN

매개변수의 스코프는 함수 내부이다.

이상적은 매개변수의 개수는 0개이며, 적을수록 좋다. 함수는 한가지 일만 해야하며 가급적 작게 만들어야 한다. 3개 이상의 매개변수가 필요하다면 하나의 매개변수를 선언하고 객체를 인수로 전달하는것이 유리하다.

2. 반환문

함수는 return 키워드와 표현식(반환값)으로 이뤄진 반환문을 사용해 실행결과를 함수 외부로 반환할 수 있다. 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나가게 하며, return 뒤에 오는 표현식을 평가해 반환한다.

function add(x, y) {
  return x + y;
  console.log('실행되지 않는다');
}

const result = add(2, 5);
console.log(result) // 7

반환문을 생략하면 암묵적으로 undefined가 반환된다.

3. 참조

원시 값은 값에의한 전달, 객체는 참조에 의한 전달방식으로 동작해 함수 호출시 인자로 객체를 전달할 경우, 함수 내부에서 인자로 전달받아 매개변수로 할당된 값을 변경할 수 있다. 따라서 외부 객체의 상태가 의도치않게 변경될 수 있는 문제가 있다.

이를 방지하기 위해 깊은복사를 통해 새로운 객체를 생성하고 재할당을 해 인자로 전달한ㄴ다.

1개의 댓글

comment-user-thumbnail
2023년 2월 14일

정리감사합니다. 도움이 많이 됐어요☺️👍

답글 달기