기술부채/프론트엔드

[JavaScript] 클로저, 호이스팅, 익명함수

생각하는렁이G 2021. 9. 22. 17:17

변수 선언 var와 let

var

(ES6 이전) 전통적인 JavaScript에는 함수 스코프와 전역 스코프 두가지만 존재했다.

var로 선언한 변수는 함수 내부 또는 외부에서 선언되었는지에 따라 함수 스코프 또는 전역 스코프를 가지게 된다. 이때 중괄호로 표시된 블록이 스코프를 생성하지 않는다는 점에서 혼란을 일으킬 수 있다.

var의 경우 선언 전에 접근할 시 undefined 이다.

 

let

let 명령문은 블록 스코프의 범위를 가지는 지역 변수를 선언할 수 있다.

ES6부터 블록은 스코프로 취급되기 시작했지만, 이는 let과 const로 변수를 선언했을 때만 유효하다.

초기화전에는 읽거나 쓸 수 없다. 초기화 전에 접근을 시도하면 RefereceError가 발생한다.

 

호이스팅

변수의 선언문을 유효범위의 최상단으로 끌어올리는 행위를 말한다. 변수가 선언되거나 함수가 실행될 때, 해당 스코프의 lesical 환경을 기억하게 되는데, 그때 변수가 최우선적으로 먼저 선언된다.

일반 함수는 함수 전체(함수명, 함수바디)가 통째로 호이스팅 되어 맨 위로 올라가기 때문에 위치 상관없이 읽을 수 있다.

 

클로저

함수 밖에서 선언된 변수를 함수 내부에서 사용할 때 클로저가 생성된다.

 

예제를 보면서 이해해보자.

변수 i가 호이스팅으로 인해 전역변수화 되고, 이를 익명함수에서 참조하여 클로저가 생성된다.

그래서 마지막 i 값이 기억되어 5로 출력된다.

var arr = [];
for(var i=0;i<5;i++){
    arr[i] = function(){
        return i;
    }
}
for(var j=0;j<arr.length;j++) {
    console.log(arr[j]());
}

// 코드 실행하면
5
5
5
5
5

 

익명함수를 한번 더 덮어서 i에 대한 참조를 독립시켜주는 클로저를 생성해보자.

var arr = [];
for(var i = 0; i < 5; i++){
    arr[i] = function(i){
      return function(){
          return i;
      }
    }(i);
}
for(var j=0;j<arr.length;j++) {
    console.log(arr[j]());
}

// 코드를 실행하면
1
2
3
4
5

 

 

좀 다르게 유용하게 사용하는 예제이다.

<script>
function makeSizer(size) {
  return function () {
    document.body.style.fontSize = `${size}px`;
  };
}

const size12 = makeSizer(12);
const size14 = makeSizer(14);
const size16 = makeSizer(16);

document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;
</script>

<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>

 

익명 함수

익명함수는 함수의 이름이 존재하지 않는다.

function() {
  console.log("hello!");
}

익명 함수는 재사용하지 않는, 한번만 사용할 함수를 위한 개념으로, 따로 함수의 이름을 갖지 않는다. 리터럴(Literal)방식으로 변수에 담겨 사용하는 함수이다. 일반적으로 변수에 데이터를 넣을 때 사용하는 방식이 리터럴 방식이다.

//익명 함수
const sayHello = function() {
  console.log("hello!");
}
sayHello(); // 출력: hello!

 

다시 말하자면, 함수가 이름을 갖는 것과 변수에 저장되는 것은 다르다. 이 차이점은 위에 언급한 호이스팅의 개념에서 온다. 

일반 함수는 함수 전체가 전부 맨 위로 올라가므로 함수를 호출하는 위치에 상관없이 사용될 수 있다. 반면, 리터럴 방식으로 사용되는 익명 함수의 경우, 호이스팅시 함수를 담는 변수의 선언부까지만 올라고, 익명 함수 자체는 변수가 호출되었을때 실행되기 때문에, 선언부가 호출위치보다 위에 있어야한다.

 

 

 

참고사이트

- 자바스크립트 클로저(Closure)

 

자바스크립트 클로저(Closure)

(2020.01.29) 스코프 관점에서 볼 수 있도록 새로 작성했습니다. 자바스크립트에는 클로저(Closure)라는 개념이 존재합니다. 프로토타입 기반의 언어인 자바스크립트는 클로저를 통해서 클래스 기반

yuddomack.tistory.com

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

 

클로저 - JavaScript | MDN

클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생

developer.mozilla.org

 

'기술부채 > 프론트엔드' 카테고리의 다른 글

[프론트엔드] SCSS 2 - 연산, 함수  (0) 2024.08.24
[프론트엔드] SCSS 1 - 변수  (0) 2024.08.19