[ JavaScript ] 클로저

초초·2023년 1월 3일
1

💻📚 TIL

목록 보기
10/22

화살표 함수

화살표를 사용하여 간단한 함수를 만들 수 있다

//1번
const add = (x, y) => x + y;

add(5,7); //12
-----------------------------------------
//2번
const adder = x => y => x + y ;

adder(5)(7); //12
adder(5) // y => x + y
typeof adder(5) // 'function'
------------------------------------------
//3번
const addermore = function (x) {        //x가 선언된 외부함수
    return function (y){                //y가 선언된 내부함수
        return x + y ;                  
    }
}

위 세 개의 함수는 모두 같은 식을 의미한다
두번째와 세번째 코드를 보면 리턴값이 함수임을 알 수 있다

클로저

함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합
클로저의 가장 큰 특징은 함수를 두번 리턴하는 함수라는 것

클로저는 리턴하는 함수에 의해 스코프가 구분되는데
핵심은 스코프를 이용해서 변수의 접근 범위를 닫는 것에 있다

const addermore = function (x) {        //x가 선언된 외부함수
    return function (y){                //y가 선언된 내부함수
        return x + y ;                  
    }
}
  • 외부함수는 y에 접근할 수 없지만 (바깥 스코프 > 안쪽 스코프)
  • 내부함수는 x에 접근할 수 있음 (안쪽 스코프 > 바깥 스코프)
  • 바깥 스코프에서 선언한 변수는 내부 함수가 사용할 수 있다

클로저는 외부 함수의 실행이 끝나더라도, 외부 함수 내 변수가 메모리 상에 저장된다

const addagain = function (x){
    return function (y){
        return x + y ;
    }
}
const add5 = addagain(5);

add5(7) //addagain(5)(7) === 12
add5(10) //addagain(5)(10) === 15

이때 add5에는 addagain함수에 있는 x에 5를 인자로 넘긴 값을 계속 저장한 채로 있음을 확인할 수 있다
이러한 특징은 다음과 같은 유용한 점을 발견할 수 있다

const htmlMaker = tag => textContent => `<${tag}>${textContent}</${tag}>`
htmlMaker('div')('hi'); //(`<${'div'}>${'hi'}</${'div'}>`)

const divmaker = htmlMaker('div'); 

이렇게 div를 할당해두면 이후 div 영역을 만들 때 언제든지 다시 꺼내어 사용할 수 있다
(그렇다면 빈 html 문서 안에 자바스크립트 만으로 웹을 만들 수 있는 걸까?)

결론

let addnum = function(x) {
    let sum = function(y) {
      return x + y;
    }
    return sum;
  }
  
  let foo = addnum(1); 
  foo(3);
  let total = foo(6); //7

let foo에 add(1)을 할당했을 때 x에 1의 값이 넘어간 채로 저장된다
foo(6)의 값을 도출할 때 내부함수에는 x의 값이 없기때문에
외부의 x를 참조해서 결과를 도출한다

이때 외부함수라는 '함수의 환경'을 참조하기 때문에 클로저의 특징을 확인할 수 있음
앞서 클로저를 함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합이라고 했는데,
내부함수가 선언되었을 때 내부함수에 필요한 인자(위의 예시에서는 x)를 외부 함수(외부의 환경)에서 주워와서 사용하고 있다는 점에서 그 의미를 약간이나마 이해할 수 있었다


클로저 모듈 패턴

클로저 모듈 패턴으로 구현 X

let ageCounter1 = {
  age: 20,
  increase: function() {
    this.age++;
  },
  decrease: function() {
    this.age--;  
  },
  getAge: function(){
    return this.age;  
  }
}

ageCounter1.increase();
ageCounter1.getAge(); // 21

클로저 모듈 패턴으로 구현 O

function makeAgeCounter() {
  let age = 20;
  return {
    increase: function() {
      age++;
    },
    decrease: function() {
      age--;
    },
    getAge: function() {
      return age;
    }
  }
}

let ageCounter1 = makeAgeCounter();
ageCounter1.decrease();
ageCounter1.getAge(); // 19

let ageCounter2 = makeAgeCounter();
ageCounter2.increase();
ageCounter2.increase();

클로저 모듈 패턴은 어떤 기능을 하는 함수를 변수에 할당하여 재사용을 가능하게 해줌

profile
잔디 꽉꽉 심쟈 🍀

0개의 댓글