인프런 강의 자바스크립트 중급 - 코딩앙마 를 듣고 정리한 내용입니다.
자바스크립트는 어휘적 환경(Lexical Environment)을 갖습니다.
let one;
one = 1;
function addOne(num){
console.log(one + num);
}
addOne(5);
위 상황에서 one
변수와 addOne
함수는 선언과 동시에 어휘적 환경으로 호이스팅 됩니다. 대신 변수는 초기화가 안된 상태라 사용 불가하고, 함수는 사용 가능합니다.
// 전역 Lexical 환경에
one: 1
addOne: function
// 내부 Lexical 환경에
num: 5
console.log(one + num);
// 여기서 일단 내부 환경에서 one 과 num 을 찾다가 없으면 외부에서 찾는다.
// 위 식에서 one 은 전역 환경, 외부 환경에 있어서 가져온 것
다른 예제도 살펴보면,
function makeAdder(x){
return function(y){
return x + y;
}
}
const add3 = makeAdder(3);
console.log(add3(2));
// 최초 실행시 전여 환경
makeAdder : function
add3 : 초기화X
const add3 = makeAdder(3);
// 위 코드가 실행되면서 만들어지는 렉시컬 환경
// makeAdder Lexical 환경
x : 3
// 넘겨받은 매개변수와 지역변수들이 저장된다.
// 동시에 add3 은 함수가 실행되었으니 리턴하는 함수가 된다.
// add3: function
console.log(add3(2));
// 마지막 줄이 실행되면서 렉시컬 환경 만들어진다.
// 익명함수 렉시컬 환경
y: 2
다른 예시를 보면,
function makeAdder(x){
return function(y){ // 이 함수는 y 를 가지고 있고 상위 함수인 makeAdder 의 x 에 접근 가능하다.
return x + y;
}
}
const add3 = makeAdder(3);
console.log(add3(2)); // add3 함수가 생성된 이후에도 상위함수인 makeAdder 의 x 에 접근 가능하다.
이런 것을 Closure
라고 합니다. 함수와 렉시컬 환경의 조합으로, 함수가 생성될 당시의 외부 변수를 기억하고, 생성 이후에고 계속 접근 가능합니다.
const add10 = makeAdder(10);
console.log(add10(5)); // 15
console.log(add3(1)); // 4
// add3 과 add10 은 서로 다른 외부 환경을 가지고 있다.
내부함수에서 외부함수의 변수에 접근해서 1씩 증가하는 코드를 만든다면,
function makeCounter(){
let num = 0; // 외부함수 변수
return function(){ // 내부 함수가 외부함수의 변수 num을 가져온다.
return num++;
};
}
let counter = makeCounter();
console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2