[JS] 스코프(Scope)

728x90

안녕하세요. 오늘은 유튜브 코드팩토리님의 자바스크립트 강의 영상을 참고하여 스코프에 대해 좀 더 자세히 작성해보도록 하겠습니다.

 

Scope란?

스코프는 변수가 유효하게 작동할 수 있는 범위를 말합니다. 쉽게 말해서 변수를 사용할 수 있는 '영역'이라고 생각할 수 있습니다.

 

 

Scope 종류

1. 전역 스코프(Global Scope)

2. 함수 스코프(Function Scope)

3. 블록 스코프(Block Scope)

 

 

전역 스코프(Global Scope)

전역 스코프는 코드 전체에서 접근할 수 있는 변수를 의미합니다. 함수 바깥이나 블록 바깥에서 변수를 선언하면 전역 스코프에 속합니다.

let globalVariable = "나는 전역 변수";

function myFunction() {
    console.log(globalVariable); // 출력 : 나는 전역 변수
}

myFunction();
console.log(globalVariable); // 출력 : 나는 전역 변수

위 코드에서 'globalVariable'은 전역 변수로, 함수 내부와 외부 모두에서 접근할 수 있습니다.

 

 

함수 스코프(Function Scope)

함수 스코프는 함수 내부에서만 접근할 수 있는 변수입니다. 'var' 키워드를 사용해서 변수를 선언하면 이 함수 스코프를 따르게 됩니다.

function myFunction() {
    var functionVariable = "나는 함수 변수";
    console.log(functionVariable); // 출력: 나는 함수 변수
}

myFunction();
console.log(functionVariable); // 오류: functionVariable은 정의되지 않음

'functionVariable'은 함수 내부에서만 유효하며 함수 바깥에서는 접근할 수 없습니다.

 

 

블록 스코프(Block Scope)

블록 스코프는 중괄호 '{}'로 둘러싸인 코드 블록 내(예를 들면 if, for, while 등)에서만 접근할 수 있는 변수를 의미합니다. 'let', 'const' 키워드를 사용하면 블록 스코프를 따르게 됩니다.

if (true) {
    let blockVariable = "나는 블록 변수";
    const blockConstant = "나는 블록 상수";
    console.log(blockVariable); // 출력: 나는 블록 변수
    console.log(blockConstant); // 출력: 나는 블록 상수
}

console.log(blockVariable); // 오류: blockVariable은 정의되지 않음
console.log(blockConstant); // 오류: blockConstant는 정의되지 않음

'blockVariable'과 'blockConstant'는 'if'문 블록 안에서만 유효하며, 블록을 벗어나면 접근할 수 없습니다.

 

 

var i = 999;
for (var i = 0; i < 10; i++) {
    console.log(i);
}
console.log(`i in global scope : ${i}`);
// 출력:
// 0 1 2 3 4 5 6 7 8 9
// i in global scope : 10

'var'는 블록 스코프를 만들지 않기 때문에 전역 스코프의 'i'를 덮어씁니다.

 

 

let i = 999;
for (let i = 0; i < 10; i++) {
    console.log(i);
}
console.log(`i in global scope : ${i}`);
// 출력:
// 0 1 2 3 4 5 6 7 8 9
// i in global scope : 999

'let'은 블록 스코프를 생성하므로 전역 스코프의 'i'와 다른 'i' 변수를 사용합니다.

 

 

var, let, const의 차이

  • var : 함수 스코프를 따릅니다. 함수 내 어디서든 접근할 수 있지만 블록 스코프를 따르지 않아 블록 외부에서도 접근이 가능합니다. 또한, 변수 선언 전에 사용할 수 있으며 이는 호이스팅이라고 합니다.
  • let : 블록 스코프(+함수 스코프)를 따릅니다. 블록 내에서만 유효하며, 변수 선언 전에 사용할 수 없습니다.
  • const : let과 마찬가지로 블록 스코프(+함수 스코프)를 따르지만 변수의 값을 변경할 수 없습니다. 반드시 선언과 동시에 초기화해야 합니다.

 

 

Lexical Scope?

자바스크립트는 Lexical Scope(또는 정적 스코프)를 따릅니다. Lexical Scope는 변수가 어디에서 선언되었는지에 따라 스코프가 결정되는 방식을 의미합니다. 이 스코프는 코드가 작성된 시점에서 결정되며 실행 시점에서 바뀌지 않습니다.

Lexical Scope : 선언된 위치가 상위 스코프를 정한다. ↔ Dynamic Scope : 실행한 위치가 상위 스코프를 정한다.

 

var numberOne = 20;
function levelOne() {
    var numberOne = 40;

    function levelTwo() {
        var numberTwo = 99;
        
        console.log(`levelTwo numberTwo : ${numberTwo}`);
        console.log(`levelTwo numberOne : ${numberOne}`); // 상위 스코프의 numberOne 출력
    }

    levelTwo();
    console.log(`levelOne numberOne : ${numberOne}`);
}
levelOne();
// 출력:
// levelTwo numberTwo : 99
// levelTwo numberOne : 40
// levelOne numberOne : 40

console.log(numberOne); // 출력: 20
console.log(numberTwo); // 오류: numberTwo는 정의되지 않음
  • 'levelTwo()' 함수는 'levelOne()' 함수의 스코프에 접근할 수 있습니다.
  • 'numberOne'는 'levelOne()' 함수에서 정의된 변수로 'levelTwo()'에서 접근 가능합니다.
  • 'numberTwo'는 'levelTwo()' 내부에서만 유효합니다. (하위 스코프에 접근할 수 없습니다.)

 

 

캡슐화와 프라이빗 변수

자바스크립트에서 스코프를 활용하여 변수를 외부에서 직접 접근하지 못하게 하고, 함수 등을 통해서만 접근할 수 있게 만들 수 있습니다. 이를 통해 캡슐화를 구현할 수 있습니다.

function Idol(name, year) {
    this.name = name; // 객체의 속성으로 설정됨
    var _year = year; // 함수 내부에서만 유효한 변수로 설정됨

    this.sayNameAndYear = function() {
        return `안녕하세요. 저는 ${this.name}입니다. ${_year}년에 태어났습니다.`;
    }
}

const yuJin = new Idol('안유진', 2003);
console.log(yuJin.sayNameAndYear()); // 출력: 안녕하세요. 저는 안유진입니다. 2003년에 태어났습니다.
console.log(yuJin.name); // 출력: 안유진
console.log(yuJin._year); // 출력: undefined

위 예제에서 'this.name'은 생성된 객체의 속성으로 설정되어 외부에서 접근할 수 있지만 'var'로 선언된 '_year' 변수는 함수 내부에서만 유효하기 때문에 외부에서 직접 접근할 수 없고 sayNameAndYear() 메서드를 통해 접근하여 '_year' 변수를 프라이빗(private) 변수처럼 사용하였습니다.

 

 

 

 

728x90