1. Lexical Scope 와 클로저(Closures)

보통 함수를 정의할 때, scope란 유효범위를 나타내는 용어이다. (물론, OS 까지 들어가면, 정확한 정의는 아니지만…)

Javascript는 함수 정의, 호출 시 Lexical scope를 따르는데, Lexical scope는 함수가 어디서 정의되었는지에 따라 상위 스코프를 결정하는 방식이다.

function init() {
    let word = 'Fire';
    function showWord() {
        console.log(word); // Fire
    }
    showWord();
}
init();

자식함수(showWord)에서 부모함수의 변수(word)를 참조할 수 있었던 이유는 자식함수가 정의되었을 때의 상위 스코프를 기억하여 부모함수의 변수를 참조할 수 있었던 까닭이다.

여기에서 클로저는 자식함수와 부모함수의 구조에서 부모함수의 변수를 참조할 수 있는 자식함수를 말한다.

내용이 많아 복잡할 수 있지만 이렇게 단순히 기억해도 될 것 같다.

  • 어떠한 함수의 변수를 다른 함수에서도 공유하고 싶다면, 공유받고 싶은 함수를 클로저로 만들어 공유받을 수 있게 할 수 있다.

아래는 직접 작성해본 클로저의 응용 예시이다.

  • 함수A에 배열을 인수로 호출하여, 페이지에 느낌표가 결합된 단어로 출력하고 싶다.
    • 예) 함수A[a, b, c] => a! b! c! 가 HTML 요소에 각각 출력
  • 함수는 2개로 구성한다. 예를 들어, 함수A는 인수를 매개변수에 전달하고 느낌표가 결합된 단어로 만들어야 하고, 함수B는 이렇게 결합된 단어를 HTML 요소에 출력해야한다.
  • 호출은 한번에 위에서 정의한 2개의 함수가 작동하도록 한다.
  • 이것이 가능하려면, 함수A와 B에서 모두 느낌표가 결합된 단어들의 배열(changeAlphabet)을 참조할 수 있어야 한다.
const row = document.querySelectorAll('.row');

const showAlphabet = (alphabets = []) => {
    
    // changeAlphabet을 공유하고 싶음
    const changeAlphabet = alphabets.map((el)=> { 
        return el + '!'
    })

    let i = 0;
    // 함수 show는 클로저
    const show = () => {
        row.forEach((el) => {
            el.innerText = changeAlphabet[i]; // a!, b!, d! 표시
            i++;
        })
    }
    show();
}

showAlphabet(['a', 'b', 'd']);

2. 클로저 체이닝

클로저는 아래와 같이 세가지 스코프를 갖게 되고, 모든 스코프에 접근할 수 있다.

  • 지역 범위
  • 외부 함수 범위
  • 전역 범뮈

// ====익명함수를 사용하여 클로저 체이닝한 예====
// 전역 범위
const sum1 = (a) => {
    return (b) => {
        return (c) => {
        	// 외부 함수 범위
            return (d) => {
            	// 지역 범위
                return a + b + c + d;
            }
        }
    }
}
 console.log(sum1(1)(2)(3)(4)) // 10


 // 익명함수 없이 클로저 체이닝한 예
 const mul1 = (a) => {
    return mul2 = (b) => {
        return mul3 = (c) => {
            return mul4 = (d) => {
                return a * b * c * d;
            }
        }
    }
 }

//  에러
//  console.log(mul1(a)(b)(c)(d));

const M1 = mul1(1);
const M2 = M1(2);
const M3 = M2(3);
const M4 = M3(4);

console.log(M4); // 24

정리

  • JS에서 중첩된 함수의 내부함수(자식함수)를 ‘클로저’라고 한다.
  • 클로저는 세개의 스코프(전역, 지역, 외부함수)를 갖게 되고, 모두 접근할 수 있다.

댓글남기기