스코프 (Scope)

TheJang·2021년 6월 13일
1

JavaScript

목록 보기
1/2
post-thumbnail

📌 스코프란?

스코프는 어떤 변수에 접근 할 수 있는지를 정의합니다. 스코프에는 동작과 레벨로 분류를 할 수 있고 동작 스코프에는 정적 스코프(Static Scope), 동적 스코프(Dynamic Scope)로 나뉘고 레벨 스코프에는 함수 스코프, 블록 스코프, 전역 스코프, 지역 스코프로 나뉩니다.

동작 스코프

  • 정적 스코프
  • 동적 스코프

레벨 스코프

  • 함수 스코프
  • 블록 스코프
  • 전역 스코프
  • 지역 스코프

스코프가 단순히 범위라고 정의를 하면 안되는 이유는 선언의 시점에 따라 값이 달라질 수 있기 때문입니다.

📌 동작 스코프

✅ 정적 스코프

javaScript는 정적 스코프의 특성을 가지고 있습니다.
정적 스코프의 규칙에 따라 호출 스택과 관계없이 선언 시점에 스코프를 결정합니다.

✅ 동적 스코프

정적 스코프와는 반대로 동적 스코프의 선언은 런타임 도중에 실행 컨텍스트나 호출 컨텍스트에 의해 결정 됩니다.

정적 스코프는 소스코드가 작성된 컨텍스트에서 결정되며, 동적 스코프는 프로그램 런타임 도중 실행 컨텍스트나 호출 컨텍스트에서 결정 됩니다.

📌 레벨 스코프

✅ 전역 스코프 (Global Scope)

만일 변수가 모든 함수에 속하지 않고 중괄호 {} 괄호 안에 들어있지도 않다면 우리는 그 변수를 전역변수(Global variable)라 부릅니다.

이는 웹 브라우저 내부의 자바스크립트의 한해서 입니다.

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 decleared

✅ 지역 스코프

코드 내 특정 구역에서만 사용할 수 있는 변수를 지역 변수라고 합니다.

자바스크립트에서는 두 가지 지역 변수가 있습니다.

  1. 함수 스코프 지역 변수
  2. 블록 스코프 지역 변수

함수 스코프 지역 변수부터 알아봅시다.

✅ 함수 스코프

함수 내에서 변수를 선언했을 때, 우리는 함수 안에서만 이 변수에 접근 할 수 있습니다. 우리가 함수 밖으로 나오게 된 이후에는 함수 내부에 있는 변수에 접근 할 수 있습니다.

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 키워드로 선언 했을 때, {} 괄호 안에서만 이 변수에 접근 할 수 있습니다.

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

console.log(hello) // Error, hello is not defined

블록 스코프는 함수 스코프의 부분 집합입니다. 함수는 {} 괄호로 작성되어야 하기 때문입니다. 물론 화살표 함수로 즉시 리턴하면 {} 없이 함수를 만들 수도 있습니다. 그렇지 않은 경우에는 모두 {} 괄호로 작성 되어야 합니다.

✅ 내부 스코프 (Nested Scope)

함수가 다른 함수 안에서 만들어졌고, 안쪽 함수는 바깥 함수의 변수에 접근 가능합니다. 이러한 것을 렉시컬 스코프 라 합니다.

하지만 바깥 함수에게는 안쪽 함수 변수에 접근할 권한이 주어지지 않습니다.

function outerFunction () {
	const outer = `I'm the outer function!`;
    
    function innerFunction() {
    	const inner = `I'm the inner function!`;
        console.log(outer) // I'm the outer function!
    }
  
  console.log(inner); // Error, inner is not defined
}

스코프가 어떻게 작동하는 지 시각화하기 위해서는 안에서는 바깥이 보이지만 바깥에서는 안이 보이지 않는 유리를 생각하면 쉽습니다.

함수의 호이스팅과 스코프

호이스팅은 끌어올리다 라는 의미를 가지고 있습니다.

function 키워드와 함께 선언된 함수들은 항상 현재 스코프의 가장 위로 호이스팅 됩니다.

그렇기 때문에 다음 코드의 결과는 다음과 같습니다.

sayHello();
function sayHello () {
	console.log('Hello CSS-Tricks Reader!');
}

// 이 코드의 결과는 위의 코드의 결과와 같습니다.
function sayHello() {
	console.log('Hello CSS-Tricks Reader!'); 
}
sayHello();

함수 표현식으로 작성된 함수들은 현재 스코프의 가장 위로 호이스팅 되지 않습니다.

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

이러한 두 가지 방법 때문에 함수 호이스팅은 헷갈릴 수 있습니다. 그리고 사용되어서는 안됩니다. 항상 함수는 사용 전에 미리 선언해야 합니다.

이러한 두 가지 방법 때문에 함수 호이스팅은 헷갈릴 수 있습니다. 항상 함수는 사용 전에 미리 선언해야합니다.

✅ 함수는 각자의 스코프에 접근할 수 없다.

함수를 각각 선언했을 때, 함수는 다른 함수의 스코프에 접근할 권한을 갖고 있지 않습니다. 심지어 함수내에서 다른 함수를 불러오더라도 스코프는 사용할 수 없습니다.

💡 정리

스코프는 어떤 변수에 접근 할 수 있는지의 범위를 말합니다. 스코프는 동작과 레벨로 분류를 할 수 있습니다. 동작 스코프에는 정적 스코프와, 동적 스코프가 있으며 정적 스코프는 호출 스택과 관계없이 선언 시점에 스코프를 결정합니다. 정적 스코프와는 반대로 동적 스코프의 선언은 런타임 도중에 실행 컨텍스트나 호출 컨텍스트에 의해 결정 됩니다. 레벨 스코프에는 전역 스코프와 지역 스코프로 분류할 수 있습니다. 전역 스코프는 변수가 모든 함수에 속하지 않으며 중괄호에도 포함 되지 않은 변수를 말합니다. 전역 변수는 말 그대로 전역에서 접근이 가능합니다. 전역 변수를 사용하게 되면 naming 충돌이 발생할 수 있으며, 가급적 최대한 사용을 지양해야합니다. 지역 스코프에는 함수 스코프와 블록 스코프로 나눌 수 있습니다. 함수 스코프는 함수 내에서 변수를 선언했을 때, 함수 안에서만 이 변수에 접근 할 수 있습니다. 함수 밖으로 나오게 되면 접근 할 수 없습니다. 함수 스코프의 생성은 함수가 생성되면서 함수 스코프가 생성됩니다. 블록 스코프는 중괄호 안에서 const나 let 키워드로 선언 했을 경우, 중괄호 안에서면 이 변수에 접근 할 수 있는 것을 말합니다.

스코프를 통해 변수 접근에 대한 실수를 줄일수 있게 되었고, 선언이 스코프에 어떠한 영향을 미치는 지 알아보게 되었습니다.

profile
어제보다 오늘 더 노력하는 프론트엔드 개발자

0개의 댓글