[JS딥다이브] 6. 함수

게코젤리·2023년 4월 21일

1. 함수란?

작업을 수행하고 값을 반환하는 코드 블럭.
코드의 중복을 막고 재사용성과 가독성을 높인다.

fuction add(x,y){ // <- 2. 매개변수로 함수 내부에 전달
	return x + y; // <- 3. 최종 값을 반환
}
add(2,3); // <- 1. 인수(argument)를 입력

2. 함수의 정의 방식

함수 정의란 함수를 호출하기 이전에 매개변수와 실행문, 반환 값을 지정하는 것을 말한다. 정의된 함수는 함수 객체가 된다.

  • 함수 객체 : 함수는 객체지만 일반 객체와는 다르다. 함수 객체는 일반 객체와 다르게 호출이 가능하고 함수 객체만의 고유한 프로퍼티를 갖는다.
  • 변수 선언과 함수 정의 : 변수가 값을 저장하는 데 사용되는 반면 함수는 코드 블록을 저장하고 실행하는 데 사용된다. 때문에 변수는 선언한다고 표현하고 함수는 정의한다고 표현한다.

2-1. 함수 선언문

function add(x,y){
	return x + y;
}
  • 함수 선언문은 표현식이 아닌 문이다.(값이 될 수 없음)
  • 함수 선언문에서는 함수 이름을 생략할 수 없다.
var plus = function add(x,y){
	return x + y;
}
plus(2,3);// 5
// 문제가 없는 코드다. 식별자를 통해 호출.
  • 표현식이 아닌 문인데 왜 위와 같이 변수에 할당 가능한 것처럼 보일까? 이유는 자바스크립트 엔진이 코드 문맥에 따라 선언문 또는 표현식으로 해석하기 때문이다. 위 코드처럼 함수를 피연산자로 사용하면 함수 선언문이 아니라 함수 표현식(함수 리터럴)으로 해석된다.
(function bar(){console.log('hi)});
bar(); // ReferenceError
// () 연산자의 피연산자로 쓰였기 때문에 함수 표현식으로 해석
  • 함수는 식별자로만 호출이 가능하다. 식별자를 선언하지 않는 함수 선언문이 호출이 가능한 이유는? 자바스크립트 엔진이 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하기 때문이다.
  • 함수 선언문으로 정의하면 런타임 이전에 함수 객체가 먼저 생성된다. 즉, 런타임에는 이미 함수 객체가 생성되어 있고 함수 이름과 동일한 식별자에 할당까지 완료된 상태다. 따라서 함수 선언문 이전에 함수를 참조할 수 있으며 호출할 수도 있다. 이를 함수 호이스팅이라한다.

2-2. 함수 표현식

  • 함수는 객체 타입의 값이다. 이처럼 값의 성질을 갖는 객체를 일급 객체라고 한다.
  • 함수는 일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있는데 이러한 함수 정의 방식을 함수 표현식이라 한다.
var plus = function (x,y){
	return x + y;
}
  • 함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문이다. 즉, 함수 표현식은 변수 호이스팅과 같은 방식으로 런타임에 함수 객체가 생성되어 변수에 할당된다. 따라서 함수 표현식 이전에 함수를 참조하면 undefined로 평가되고 이때 함수를 호출하면 타입 에러가 발생한다.

2-3. 화살표 함수

  • 화살표 함수는 항상 익명 함수로 정의한다.
  • 생성자 함수로 사용 불가
  • 기존 함수와 this 바인딩 방식이 다르다
  • prototype 프로퍼티가 없다.
  • arguments 객체를 생성하지 않는다.

3. 함수 호출

3-1. 매개변수와 인수

  • 매개변수는 함수를 정의할 때 선언하며 함수 내부에서 변수와 동일하게 취급된다. 함수가 호출되면 매개변수는 일반 변수와 마찬가지로 undefined로 초기화된 이후 인수가 순서대로 할당된다.
  • 초과된 인수는 무시되고 암묵적으로 arguments 객체의 프로퍼티로 보관된다.

3-2. 참조에 의한 전달

  • 함수를 호출하면서 매개변수에 값을 전달하는 방식을 call by value, call by reference로 구분한다.
  • 원시타입의 인수는 값 자체가 복사되어 매개변수에 전달되므로 함수 내부에서 그 값을 변경해도 원본이 영향이 없다.
  • 참조 타입의 인수는 값 자체가 아니라 참조(값의 주소)값이 복사되어 매개변수에 전달되므로 함수 내부에서 그 값을 변경하면 원본도 변경된다.
  • 따라서 함수 내부에서 객체의 상태 변경이 필요한 경우, 원본 객체를 완전히 복제(깊은 복사)하여 새로운 객체를 생성하고 재할당을 통해 교체하면 부수 효과를 없앨 수 있다.

3-3. return

  • 함수의 실행을 중단하고 함수를 빠져나간다.
  • return 키워드 뒤에 오는 표현식을 평가해 반환하고 없으면 undefined를 반환한다.

4. 함수의 형태

4-1. 즉시 실행 함수

  • 함수 정의와 동시에 즉시 호출, 재호출할 수 없다.
(function foo() {
  var a = 3;
  var b = 5;
  return a * b;
})();
foo(); // ReferenceRrror: foo is not defined

4-2. 재귀 함수

  • 함수가 자기 자신을 호출하는 함수
function countdown(n) {
  if (n < 0) return;
  console.log(n);
  countdown(n - 1); // 재귀 호출
}
countdown(10);

4-3. 콜백 함수

  • 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
  • 이때 매개 변수를 통해 함수 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다.
  • 고차 함수는 콜백함수를 자신의 일부분으로 합성한다.
function repeat(n, f) {
  for (var i = 0; i < n; i++) f(i);
}
const logAll = function (i) {
  console.log(i);
};
repeat(5, logAll);

4-4. 순수 함수

  • 외부 상태에 의존하지도 변경하지도 않는, 부수 효과가 없는 함수
  • 최소 하나 이상의 인수를 전달 받는다. (그렇지 않으면 상수)
  • 인수의 불변성을 유지한다.

📖 모던자바스크립트 딥다이브 12장 함수(154p)

0개의 댓글