[JavaScript] Scope and Closure

Fleuve·2020년 9월 15일
0
post-thumbnail

목차

  • 스코프(Scope)
  • 호이스팅(Hoisting)
  • 클로저(Closure)

1. Scope란?

자바스크립트를 공부하다 보면 Scope라는 키워드를 자주 접하게 됩니다.

Scope는 우리말로 번역하면 범위라는 뜻을 가지고 있다. 즉, Scope는 변수 접근 규칙에 따른 유효 범위를 말한다.

자바스크립트는 기본적인 함수가 선언되는 동시에 자신 만의 Score(lexical scope)를 가지게 되고 Scope는 2가지 타입인 전역 스코프(Global Scope)와 지역 스코프(Local Scope)가 있다.

전역 스코프

변수가 함수 바깥이나 중괄호({}) 바깥에 선언되었다면 전역 스코프로 정의된다.

let greeting = 'Hello World';
function greetSomeone() {
  console.log(greeting);
}
greetSomeone(); // 'Hello World';
console.log(greeting); // 'Hello World';

전역 스코프는 최상단의 스코프로, 전역 변수는 어디서든 접근이 가능하다. 이렇게 함수 바깥쪽에 선언한 변수도 함수 내에서 사용이 가능하다. 하지만 전역 범위에 너무 많은 변수를 선언하는 것은 지양해야 한다. 그 이유는 두 개 이상의 변수의 이름이 충동하는 경우가 생길 수도 있기 때문이다. 만약 let이나 const 키워드를 사용한 경우 변수명에 충돌이 발생할 때마다 아래 예 처럼 에러가 발생한다.

let greeting = 'Hello World';
let greeting = 'Hello JavaScript'; //Identifier 'greeting' has already been declared

혹은 var 키워드를 사용했을 경우 첫 번째 변수 값을 두 번째 변수가 덮어쓰게 되면서 원하는 결과 값을 얻어내기가 힘들어진다. 그래서 전역변수가 아닌 지역변수로 선언하는 것을 지향해야 한다.

지역 스코프

지역 스코프는 중괄호({})로 시작하고 끝나는 단위로 중괄호 내부에서만 접근할 수 있다. 이러한 변수 들을 지역 변수라고한다.

자바스크립트에서 지역 변수는 함수 스코프와 블로 스코프 두 가지 종류가 있다.

함수 스코프(Function Scope)

함수 스코프는 함수 내에 선언된 변수는 함수 내부에서만 접근이 가능하다.
아래 코드를 보면 함수 내에 hi는 잘 출력이 되지만 함수 외부에서 호출한 hi는 찾을 수 없다는 에러 메시지를 보낸다.

function sayHello() {
  let hi = 'Hello JavaScript';
  console.log(hi);
}
sayHello(); // 'Hello JavaScript'
console.log(hi); // Error, hi is not defined

블록 스코프(Block Scope)

블록 스코프는 중괄호({}) 내부에서 let, const 키워드로 변수를 선언하게 되면 이 변수는 중괄호 내부에서만 접근이 가능하다.

아래 코드를 보면 hi는 중괄호 내부에서만 동작하는 것을 볼 수 있다.

{
  let hi = 'Hello JavaScript';
  console.log(hi); //'Hello JavaScript'
}
console.log(hi); // Error, hi is not defined

2. 호이스팅(hoisting)

호이스팅을 우리 말로 번역하면 끌어 올리다라는 뜻이다. 자바스크립트에서의 호이스팅은 어디에 선언했느냐에 상관없이 항상 제일 위로 선언을 끌어 올리는걸 말한다.

sayHello();
function sayHello() {
  console.log('Hello World');
}

function sayBye() {
  console.log('bye bye');
}
sayBye();

위에 보이는 두 가지 경우는 에러 없이 잘 실행된다.

반면 화살표 함수로 표현을 한다면 호이스팅이 되지 않는다.

sayHello(); // Error, sayHello is not defined
const sayHello = () => {
  console.log('Hello World');
}

이렇게 두 방식의 행동이 다르기 때문에 함수 호이스팅은 혼란스러울 수 있기 때문에 사용하면 안 된다.
언제나 함수를 호출하기 전에 선언을 해야한다.

3. 클로저(Closure)

외부 함수의 변수에 접근할 수 있는 내부함수를 클로저라고 한다.
클로저는 차후에 외부 함수의 변수를 사용할 수 있기 때문에 대부분 반환하여 사용을 합니다.

function adder(x) {
  return function(y) {
    return x + y;
  }
}
adder(2)(3); //5

위 예제는 커링이라고 하는 방법으로 유용한 클로저의 예제이다.

adder(2)를 JavaScript 콘솔에 찍어보면 아래와 같은 함수를 리턴하게된다.

function(y) {
  return x + y;
}

먼저 adder(2)가 실행되면 위의 함수를 리턴한다. 저 함수 내에서 x는 2로 기억되고 있다. 그리고 adder(2)의 결과를 바로 그 다름인 3이라는 인자 값을 넘기면 5라는 결과가 나오게된다.

let add100 = adder(100);
add100(2); //102
add100(10); //110

adder(100)이 실행되는 순간, 이 함수가 리턴하는 익명함수는 클로저가 된다. 이 익명함수에서는, x가 정의 되지는 않았지만 클로저는 그 함수가 실행된 환경을 기억하고 있기 때문에 x = 1이라는 사실을 가지고 함수를 실행하게된다.

커링

함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게하는 방법

0개의 댓글