Post

Deep Dive 12. 함수

함수 정의

함수 정의와 방식예시
함수 선언문function add (x,y){ return x + y; }
함수 표현식var add = function (x,y) { return x + y; };
Function 생성자 함수var add = new Fucntion(‘x’, ‘y’, ‘return x + y’);
화살표 함수(ES6)var add = (x,y) => x + y;

함수 선언문이 평가되면 식별자가 암묵적으로 생성되고 함수 객체가 할당된다. 따라서 ECMAScript 사앙헤서도 변수에는 선언, 함수에는 정의라고 표현한다.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 함수 참조
console.dir(add); // f add(x, y)
console.dir(sub); // undefined

// 함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)) // TypeError : sub is not a function

// 함수 선언문
function add (x, y){
  return x + y;
}

// 함수 표현식
var sub = function (x, y){
  return x + y;
};

함수를 선언문으로 정의한 경우 함수 호이스팅이 발생한다. 그 이유는 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성되고 자바스크립트 엔진이 암묵적으로 함수 이름과 동일한 이름의 식별자를 생성하기 때문이다.

반면 함수 표현식으로 정의한 경우, 함수 표현식은 런타임에 평가되어 함수 객체가 된 후 변수에 할당된다. 따라서 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생하는 것이다.

Function 생성자 함수

1
2
3
var add = new Function('x','y', 'return x + y');

console.log(add(2,5));

Function 생성자 함수로 생성한 함수는 클로저를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var add1 = (function() {
  var a = 10;
  return function (x, y){
    return x + y + a;
  };
}());

console.log(add1(1,2)); // 13

var add2 = (function () {
  var a = 10;
  return new Function('x', 'y', 'return x + y + a;');
}());

console.log(add2(1, 2)); // ReferenceError: a is not defined

클로저에 대해서 아직은 배우지 않았지만 함수 선언문이나 함수 표현식으로 생성한 함수와 Function 생성자 함수로 생성한 함수가 동일하게 동작하지 않는다는 데 주목하자.

화살표 함수

ES6에서 도입된 화살표 함수는 function 키워드 대신 화살표 =>를 사용해 좀 더 간략한 방법으로 함수를 선언할 수 있다. 화살표 함수는 항상 익명 함수로 정의한다.

1
2
3
// 화살표 함수
const add = (x,y) => x + y;
console.log(add(2,5)); // 7

화살표 함수와 일반 함수 차이점

  • 생성자 함수로 사용할 수 없다.
  • this 바인딩 방식이 다르다.
  • prototype 프로퍼티가 없다.
  • arguments 객체를 생성하지 않는다.

콜백 함수

1
2
3
4
5
// 익명 함수 리터럴을 콜백 함수로 고차 함수에 전달한다.
// 익명 함수 리터럴은 repeat 함수를 호출할 때마다 평가되어 함수 객체를 생성한다.
repeat(5, function(i){
  if(i % 2) console.log(i);
})

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 한다. 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다.

콜백 함수가 고차 함수 내부에만 호출된다면 콜백 함수를 익명 함수 리터럴로 정의하면서 곧바로 고차 함수에 전달하는 것이 일반적이다.

콜백 함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리(이벤트 처리, Ajax 통신, 타이머 함수 등)에 활용되는 중요한 패턴이다.

순수 함수와 비순수 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
var count = 0; // 현재 카운트를 나타내는 상태

// 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환한다.
function increase(n) {
  return ++n;
}

// 순수 함수가 반환한 결과값을 변수에 재할당해서 상태를 변경
count = increase(count);
console.log(count); // 1

count = increase(count);
console.log(count); // 2

순수 함수란 어떤 외부 상태에 의존하지 않고 변경하지도 않는, 즉 부수 효과가 없는 함수를 의미한다. increase는 인수로 받은 값, 즉 자신의 내부에 값만 변경시킨다.

내부상태에만 의존한다고 해도 그 내부 상태가 호출될 때마다 변화하는 값(ex: 현재 시간)이라면 순수함수가 아니다. {. prompt-danger}

1
2
3
4
5
6
7
8
9
10
11
12
13
var count = 0; // 현재 카운트를 나타낸는 상태: increase 함수에 의해 변화한다.

// 비순수 함수
function increase(){
  return ++count; // 외부 상태에 의존하며 외부 상태를 변경한다.
}

// 비순수 함수는 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려워진다.
increase();
console.log(count); // 1

increase();
console.log(count); // 2

비순수 함수란 외부 상태에 의존하거나 외부 상태를 변경하는, 즉 부수 효과가 있는 함수를 의미한다.

함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 부수효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임이다.

This post is licensed under CC BY 4.0 by the author.