클로저와 고차 함수

함수형 프로그래밍 개념을 알기 전에 자바스크립트에서 클로저를 이해해야 한다.

클로저의 이해

클로저

간단히 얘기해 클로저는 내부 함수다. 내부 함수란 간단히 다음과 같이 다른 함수 내에 있는 함수다.

1
2
3
4
5
function outer() {
function inner() {

}
}

이것이 클로저다. inner 함수를 클로저 함수라고 부른다. 클로저는 스코프 사슬(scope chain) 에 접근할 수 있어 유용하다.
기술적으로 클로저는 세 개의 스코프를 갖고 있다.

  1. 자체 선언 내에서 선언된 변수
  2. 전역 변수에 접근
  3. 외부 함수의 변수에 접근

간단한 예제를 통해 세 부분을 각각 알아본다.

1
2
3
4
5
6
7
8
function outer() {
function inner() {
let a = 5;
console.log(a);
}

inner();
}

inner 함수가 호출되면 콘솔에 5가 출력된다. 이는 첫 번째에 살펴본 관점 때문이다. 클로저 함수는 각기 선언된 변수에
모두 접근할 수 있다.

1
2
3
4
5
6
7
8
9
let global = "global";
function outer() {
function inner() {
let a = 5;
console.log(global);
}

inner();
}

inner 함수가 실행되면 global 변수가 출력된다. 따라서 클로저는 전역 변수에 접근할 수 있다.

1
2
3
4
5
6
7
8
9
10
let global = "global";
function outer() {
let outer = "outer";
function inner() {
let a = 5;
console.log(outer);
}

inner();
}

inner 함수가 실행되면 outer 값을 출력한다. 적절한 결과인 것 같지만, 클로저의 중요한 속성이다.
클로저는 외부 함수의 변수에 접근했다. 여기서 외부 함수는 클로저 함수를 감싸는 함수다.

어디서부터 생겨났을까?

1
2
3
4
5
6
7
8
9
var fn = (arg) => {
let outer = "Visible";
let innerFn = () => {
console.log(outer);
console.log(arg);
}

return innerFn;
}

코드는 간단하다. innerFn 은 fn 에 대한 클로저 함수이고, fn 이 호출되면 innerFn 울 반환한다.

1
2
3
4
var closureFn = fn(5);
closureFn();
// Visible
// 5

동작되는 과정을 살펴보면 다음과 같다.

  1. var closureFn = fn(5); 코드가 호출되면 fn 은 인자 5를 받고 호출된다. fn 정의가 이뤄지면 innerFn 을 반환한다.
  2. innerFn 이 반환되면 자바스크립트 실행 엔진은 innerFn 을 클로저로 보며, 그에 따라 스코프를 지정한다. 앞에서 살펴 봤듯이 클로저는 세 개의 스코프 레벨에 접근할 수 있다. 반환된 함수 참조는 closureFn 내에 저장된다.

sortBy 함수 살펴보기

sortBy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const sortBy = (property) => {
return (a, b) => {
const result = (a[property] < b[property]) ? -1 :
(a[property] > b[property]) ? 1 : 0;

return result;
}
}

const people = [
{firstname: "lee"},
{firstname: "park"},
{firstname: "kim"}
];

console.log(people.sort(sortBy("firstname")));
/**
[
{firstname: "kim"},
{firstname: "lee"},
{firstname: "park"}
]
*/

참조: 함수형 자바스크립트 입문 2/e

댓글

You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.