JavaScript

JavaScript Scope 와 Closure

반응형

<Scope>

 

Scope란 변수에 접근할 수 있는 범위를 나타냅니다.

 

블록 레벨 스코프(Block-Level Scope)를 따르는 C계열 언어들과 다르게 자바스크립트는 함수 레벨 스코프(Functional-Level Scope)를 따릅니다.

 

다음을 보면

function num() {
  var x = 10
}

console.log(x) // ReferenceError: x is not defined

x는 num() 이라는 함수 안에 선언이 되었기에 ReferenceError가 납니다.

즉, 외부에서는 접근하지 못합니다.

 

반면 다음을 보면

if (true) {
  var x = 10
}

console.log(x) // 10

x는 if문 안에 선언이 되었습니다. C계열의 언어라면 블록안에 선언되어 접근하지 못했겠지만 자바스크립트의 경우 if문은 함수가 아니기 때문에 x는 전역에서 사용가능한 전역변수가 됩니다.

 

단! ECMAScript6 부터 적용된 let 을 사용하면 블록 레벨 스코프(Block-Level Scope)를 사용할 수 있습니다. 

 

 

<Lexical Scope>

function first() {
  var x = 10
  second()
}

function second() {
  console.log(x)
}

second() // ReferenceError: x is not defined
  1. 함수를 어디서 호출하였는가 => 동적 스코프(Dynamic Scope)
  2. 함수를 어디서 선언하였는가 => 렉시컬 스코프(Lexical Scope) 혹은 정적 스코프(Static Scope)

자바스크립트를 비롯한 대부분의 언어는 렉시컬 스코프를 따릅니다.

 

다시말해 렉시컬 스코프는 어디서 호출하였는지가 아니라 어디에 선언하였는지에 따라 결정되는 것을 말합니다.

 

 

<Closure>

Closure 란 함수와 그 함수를 둘러싼 환경의 조합이라고 정의합니다. 

 

이 개념은 자바스크립트에만 국한되는게 아닌 함수형 프로그래밍 언어(Functional Programming Language)에서 나타나는 특성입니다.

 

자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부함수 밖에서 내부함수가 호출되더라도 외부함수 내의 변수에 접근할 수 있는 함수들을 Closure라고 부릅니다.

 

모든 함수가 선언될 때마다 클로저가 만들어지게 됩니다.

 

예를 들어

function getCounter() {
  var result = { count: count, total: 0 }
  function count() { result.total += 1 }
  return result
}

var counterA = getCounter()
counterA.count()
counterA.count()

var counterB = getCounter()
counterB.count()

console.log(counterA.total, counterB.total)

 정답은 2, 1 이 된다.

couter 의 클로저가 다르기 때문에 그렇습니다.

반응형