# 반환 함수
function makeCounter() { LexicalEnvironment global Lexical Environment
let count = 0; --- of makeCounter() call
return function() { | makeCounter: function
return count++; | count: 0 --outer--> counter: undefined --outer--> null
} |
} ___
let counter = makeCounter();
1
2
3
4
5
6
7
2
3
4
5
6
7
makeCounter()를 호출
할 때마다, (익명함수
에 대한) 새로운 렉시컬 환경 객체
가 만들어 진다.
중첩 함수
가 생성이 되고실행은 되지 않은
상태
# JS 모든 함수는 클로저
- 클로저란 내부함수가 외부함수의 지역변수에 접근 할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 의미한다
호출 장소와 상관없이 모든 함수
는 함수가 생성된 곳
의 렉시컬 환경을 기억
한다.
- 함수는
[[Environment]]
라 불리는숨김 프로퍼티
를 갖는다- 함수가 만들어진 곳의
렉시컬 환경에 대한 참조
가 저장된다. - 생성될 때,
딱 한번
그 값이 세팅된다.
- 함수가 만들어진 곳의
function makeCounter() {
let count = 0; ---
return function() { [[Environment]] --> | makeCounter: function
return count++; | count: 0 --outer--> counter: undefined --outer--> null
} |
} ---
let counter = makeCounter();
1
2
3
4
5
6
7
2
3
4
5
6
7
counter()
(makeCounter() 의 반환함수인 익명함수) 를 호출할 때마다, 새로운 렉시컬 환경이 만들어진다.
새로운 렉시컬 환경이지만, counter.[[Environment]]에 저장된 렉시컬 환경을 외부 렉시컬 환경으로서 참조
- counter()의 렉시컬 환경은 매번 만들어 지지만, makeCounter() 렉시컬은 별개로 새로 만들어 지지 않는 상태이다.
- counter()에서 외부 렉시컬 환경의 변수를 참조할 때에는 딱 한번 만들어지는 counter.[[Environment]] 를 참조한다.
싱글톤 같은 개념인가?
변수값 갱신은 변수가 저장된 렉시컬 환경에서 이뤄진다.
counter()
을 여러번 호출하면 count 변수가 2, 3 .. 으로 증가하는 이유
# 클로저
외부변수를 기억하고 이 외부 변수에 접근할 수 있는 함수
# 클로저는 언제 사용할까?
자바스크립트 라이브러리나 모듈에서 private 으로 나의 변수를 보호하고 싶을 때. 즉, 지역 변수 보호
function hello(name) { var _name = name; return function() { console.log('Hello, ' + _name); }; } var hello1 = hello('승민'); var hello2 = hello('현섭'); var hello3 = hello('유근'); hello1(); // 'Hello, 승민' hello2(); // 'Hello, 현섭' hello3(); // 'Hello, 유근'
1
2
3
4
5
6
7
8
9
10
11
12
13
14- 사용자의 접근을 제한
- 변수의 조작을 불가능하게 하기 위함.
모듈 에서 한번 더 다룰 예정이다. TODO
static 변수를 이용
하고 싶을 때- 다른 라이브러리들과 함께 사용되는 경우 서로간 충돌을 없앰
- 전역변수를 사용했다가 다른 라이브러리 가져왔는데 그 라이브러리에서 덮어씌워버린다면 이유도 모르고 멀쩡하던 웹 페이지에서 에러가 발생하게 될 것이다.
# 가비지 컬렉션
일반적으로, 함수 호출이 끝나면
함수의 렉시컬 환경이 메모리에서 제거
된다.
# 메모리에 유지되는 경우 🔗
도달 가능한 상태일 때
중첩함수
에서[[Environment]]
프로퍼티에외부 함수 렉시컬 환경에 대한 정보가 저장
되어. 도달 가능한 상태가 된다.- 해제 :
g = null;
# 최적화 프로세스
자바스크립트 엔진는 외부 변수가 사용되지 않는다고 판단되면 메모리에서 제거한다.
- V8, 디버깅시 클로저의 변수를 사용할 수 없는 부작용이 있다.
# code
함수의 콜백의 이름이 있는 함수를 쓴다.
function inBetween(a, b) {
return function(x) {
return x a && x <= b;
};
}
let arr = [1, 2, 3, 4, 5, 6, 7];
alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
1
2
3
4
5
6
7
2
3
4
5
6
7
필드를 기준으로 정렬하기
let users = [
{ name: "John", age: 20, surname: "Johnson" },
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" }
];
function byField(field) {
return (a, b) => a[field] > b[field] ? 1 : -1;
}
users.sort(byField('name'));
users.sort(byField('age'));
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11