ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS] Closure
    Web/JS 2022. 5. 12. 01:10
    SMALL

    자바스크립트에서 함수의 유효범위는 그 함수를 어디에서 실행됐는냐가 아니라 어디서 정의됐느냐에 따라 달라진다.

    자바스크립트는 static (lexical) scope(함수 선언은 한 번밖에 못하는데 이거를 static, 정적이라 칭함)를 채택한다.

     

    클로저란

    부모 함수 안에서 자식 함수를 선언하면 자식함수를 어디에서 호출하더라도 자식함수 안에서 부모함수의 변수에 접근할 수 있다는 것을 의미한다!

     

     

    프리코드캠프 글에서 살펴본 예시를 가져왔다. 아래와 같은 함수가 있다고 해보자.

    let count = 1
    function counter() {
        console.log(count)
    }
    counter() // print 1

     

    함수의 큰 장점은 재사용성인데,

    이 함수를 다양한 곳에서 재사용하고 싶기 때문에 아래와 같이 또 다른 함수에다 집어넣을 수 있을 것이다.

     

    function wrapper() {
        let count = 1
        function counter() {
            console.log(count)
        }
        counter() // print 1
    }

    여기서

    counter 함수: counter 바깥에서 선언된 count라는 변수를 사용한다.

    count: wrapper 함수 스코프에서 선언됐지만 counter 함수안에서 사용된다.

     

    즉, 우리는 컨텍스트 바깥에서 선언된 값을 사용하는 함수를 가지는 것인데, 그게 바로 클로저라 할 수 있다!

     

    그럼 wrapper함수가 실행될 때, count 변수와 counter 함수에는 어떤 일이 일어날까?

    wrapper 안에서 선언된 변수들과 함수들은 “사라진다”(가비지 콜렉터에 의해)

     

     

    예시를 아래와 같이 살짝 수정해보자.

    function wrapper() {
        let count = 1
        function counter() {
            count++
            console.log(count)
        }
       setInterval(counter, 2000)
    }
    wrapper()

    이 예시에서 우리는 브라우저한테 counter함수를 2초마다 실행하라고 말하는 것과 같다.

    그래서 자바스크립트 엔진은 함수(counter)와 변수(count)에 대한 reference를 keep해야한다.

    심지어 부모함수인 wrapper가 실행 사이클을 끝낸 후에도 counter 함수와 count 값은 여전히 “살아있다”

     


    그렇다면 자바스크립트에서 클로저는 주로 뭐할 때 쓰일까?

     

    1. IIFE(즉시호출함수)

    const module = (function(){
    	function privateMethod () {
    	}
    	const privateValue = "something"
    	return {
    	  get: privateValue,
    	  set: function(v) { privateValue = v }
    	}
    })()
    
    var x = module()
    x.get() // "something"
    x.set("Another value")
    x.get() // "Another Value"
    x.privateValue //Error
    
    
    //프라이빗한 변수를 함수내 모듈 자체에 의해서만 사용할 수 있게 해준다.

     

     

    2. Function Factory(함수 찍어내는 공장)

    즉, 함수로 다른 함수나 객체를 만들 때 사용된다.

    function 더하기함수공장(초기값){
    	function 덧셈(숫자){
    		return 초기값+숫자 //초기값은 상위 부모함수에게서 가져온다!
    	}
    	return 덧셈;
    }
    
    let 더하기1=더하기함수공장(1);
    console.log(더하기1(1))
    console.log(더하기1(2))
    
    let 더하기2=더하기함수공장(2);
    console.log(더하기2(1))
    console.log(더하기2(2))

     

    3. Currying

    :여러 인자를 받는 함수를 단일 인자를 받는 함수의 체인으로 이용하는 방식으로 바꾸는 것

    (함수형프로그래밍 방식 중 하나)

    function multiply(a) {
    
        return function (b) {
            return function (c)  {
                return a * b * c
            }
        }
    }
    let mc1 = multiply(1);
    let mc2 = mc1(2);
    let res = mc2(3);
    console.log(res);
    
    let res2 = multiply(1)(2)(3);
    console.log(res2);

     

    4. 이벤트리스너 (리액트)

    // Closure
    // with es5
    function onItemClick(title) {
        return function() {
          alert("Clicked " + title)
        }
    }
    // with es6
    const onItemClick = title => () => alert(`Clcked ${title}`)
    
    return (
      <Container>
    {items.map(item => {
    return (
       <RenderItem onClick={onItemClick(item.title)}>
        <Title>{item.title}</Title>
      </RenderItem>
    )
    })}
    </Container>
    )

     

     

    *생활코딩과 freecodecamp를 참고하여 적은 글입니다.

    https://www.youtube.com/watch?v=bwwaSwf7vkE

    https://www.freecodecamp.org/news/closures-in-javascript/#:~:text=What%20is%20a%20closure%20in,variable%20defined%20outside%20its%20context.&text=You%20use%20the%20value%20of,outside%20of%20the%20function%20itself.

    반응형

    'Web > JS' 카테고리의 다른 글

    [JS] Constructor Function  (0) 2022.05.06
    [JS] 정규표현식(Regular Expressions)  (0) 2022.02.11
    [JS] 소수점을 버리고 자연수를 얻는 방법  (0) 2022.01.17

    댓글

Designed by Tistory.