스코프와 클로저는 자바스크립트에서 굉장히 중요합니다. 하지만 제가 처음 자바스크립트를 시작할 때 이 두 개념이 굉장히 헷갈렸어요. 대체 스코프와 클로저가 무엇인지, 여러분이 이해할 수 있도록 도와드리고자 이 글을 준비했습니다.

그럼, 스코프부터 시작해 보도록 하죠.

스코프(Scope)

자바스크립트에서 스코프란 어떤 변수들에 접근할 수 있는지를 정의합니다. 스코프엔 두 가지 종류가 있는데요, 전역 스코프(global scope)와 지역 스코프(local scope)가 있죠.

전역 스코프(Global Scope)

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

이 설명은 웹 브라우저의 자바스크립트에만 유효합니다. Node.js에서는 전역 스코프를 다르게 정의하지만, 이번 글에서는 다루지 않겠습니다.
const globalVariable = 'some value'

전역 변수를 선언하면, 여러분의 코드 모든 곳에서 해당 변수를 사용할 수 있습니다. 심지어 함수에서도 말이죠.

const hello = 'Hello CSS-Tricks Reader!'
function sayHello () {
console.log(hello)
}
console.log(hello) // 'Hello CSS-Tricks Reader!'
sayHello() // 'Hello CSS-Tricks Reader!'

비록 전역 스코프에 변수를 선언할 수는 있어도, 그러지 않는 것이 좋습니다. 왜냐하면, 두 개 이상의 변수의 이름이 충돌하는 경우가 생길 수도 있기 때문이죠. 만약 변수를 const나 let을 사용하여 선언했다면, 이름에 충돌이 발생할 때마다 에러가 발생합니다. 이렇게 되면 안 되죠.

// Don’t do this!
let thing = 'something'
let thing = 'something else' // Error, thing has already been declared

만약 var를 이용하여 변수를 선언했다면, 두 번째 변수가 첫 번째 변수를 덮어쓰게 됩니다. 이러면 디버깅이 어려워지기 때문에 이런 식으로 사용하면 안 됩니다.

// Don’t do this!
var thing = 'something'
var thing = 'something else' // perhaps somewhere totally different in your code
console.log(thing) // ‘something else’

그래서 여러분은 언제나 전역 변수가 아닌, 지역 변수로써 변수를 선언해야 합니다.

지역 스코프 (Local Scope)

여러분 코드의 특정 부분에서만 사용할 수 있는 변수는 지역 스코프에 있다고 할 수 있습니다. 이런 변수들은 지역 변수라고 불리죠.

자바스크립트에서는 두 가지의 지역 변수가 존재합니다. 바로 함수 스코프(function scope)와 블록 스코프(block scope)죠.

먼저 함수 스코프부터 알아보도록 합시다.

함수 스코프(Function Scope)

여러분이 함수 내부에서 변수를 선언하면, 그 변수는 선언한 변수 내부에서만 접근할 수 있습니다. 함수 바깥에서는 해당 변수에 접근할 수 없죠.

->함수스코브 :var let const어떤 걸로 선언하든 선언한 함수내부에서 선언한 것은 함수내부에서만 사용가능

아래의 예제를 살펴보면 변수 hello는 sayHello의 스코프 내에 존재한다는 것을 알 수 있습니다.

function sayHello () {
const hello = 'Hello CSS-Tricks Reader!'
console.log(hello)
}
sayHello() // 'Hello CSS-Tricks Reader!'
console.log(hello) // Error, hello is not defined

블록 스코프(Block Scope)

여러분이 중괄호({}) 내부에서 const 또는 let으로 변수를 선언하면, 그 변수들은 중괄호 블록 내부에서만 접근할 수 있습니다.

->블록스코프:블록 내부에서 let const로 선언한 것은 블록 내부에서만 사용가능. 단 var은 블록 내부에서 선언해도 밖에서 사용가능

다음 예제에서 볼 수 있듯이 변수 hello는 중괄호 내부의 스코프에 존재합니다.

{
const hello = 'Hello CSS-Tricks Reader!'
console.log(hello) // 'Hello CSS-Tricks Reader!'
}
console.log(hello) // Error, hello is not defined

함수를 선언할 때는 중괄호를 사용해야 하므로 블록 스코프는 함수 스코프의 서브셋(subset) 입니다(여러분이 화살표 함수(arrow function)를 사용해서 암시적(implicit) 반환을 하는게 아니라면 말이죠).

함수 호이스팅(Function hoisting)과 스코프

함수가 함수 선언식(function declaration)으로 선언되면, 현재 스코프의 최상단으로 호이스팅(hoist) 됩니다.

다음 예제에서 두 가지 경우는 같은 결과를 보입니다.

// This is the same as the one below
sayHello()
function sayHello () {
console.log('Hello CSS-Tricks Reader!')
}
// This is the same as the code above
function sayHello () {
console.log('Hello CSS-Tricks Reader!')
}
sayHello()

반면 함수가 함수 표현식(function expression)으로 선언되면, 함수는 현재 스코프의 최상단으로 호이스팅되지 않습니다.

sayHello() // Error, sayHello is not defined
const sayHello = function () {
console.log(aFunction)
}

이렇게 두 방식의 행동이 다르기 때문에, 함수 호이스팅은 혼란스러울 수 있으므로 사용하면 안 됩니다. 언제나, 함수를 호출하기 전에 선언해놓아야 합니다.

+ Recent posts