본문 바로가기
Front-end/React

Scope,호이스팅,this 이해하기 [Javascript]

by 지니어스팍 2023. 12. 15.

♥ 목차 ♥

    728x90
    728x90

    Scope

    "스코프(scope)"는 프로그래밍에서 변수 및 함수의 유효 범위를 나타내는 용어이다.

    스코프는 코드 내에서 식별자(변수 또는 함수의 이름)에 대한 유효성을 제공하며, 변수 또는 함수가 어디서 접근 가능한지를 결정한다.

     

    하위 스코프와 상위 스코프 접근 가능 여부

    하위 스코프는 상위 스코프에 접근할 수 있지만 상위 스코프는 하위 스코프에 접근할 수 없다.

    아래 두 코드로 비교해볼 수 있다.

    // 상위 스코프
    var outerVar = "I'm in the outer scope";
    
    function outerFunction() {
        // 하위 스코프
        var innerVar = "I'm in the inner scope";
    
        function innerFunction() {
            // 더 하위 스코프
            var deepestVar = "I'm in the deepest scope";
            console.log(outerVar);    // 상위 스코프의 변수에 접근 가능
            console.log(innerVar);    // 직접적인 상위 스코프의 변수에 접근 가능
            console.log(deepestVar);  // 직접적인 상위 스코프의 변수에 접근 가능
        }
    
        innerFunction();
    }
    
    outerFunction();

     

    정적 (렉시컬) 스코프 (lexical scope) 와 동적 스코프

    자바스크립트는 정적 스코프를 쓰지 않고 렉시컬 스코프의 사용이 권장된다.

     

    정적(static) 스코프 ( = 렉시컬 스코프)

    렉시컬 스코프는 함수를 어디에 작성했는지에 따라 결정되는 스코프의 형태를 의미한다.

    함수가 어디에서 호출되는지가 아니라 어디에 선언되었는지에 따라 해당 함수의 스코프가 정적으로 결정된다.

    이것은 코드를 작성하는 시점에 스코프가 정해지고, 실행 컨텍스트에 따라 동적으로 바뀌지 않음을 의미한다.

    function outer() {
        var outerVar = "I'm in the outer function";
    
        function inner() {
            var innerVar = "I'm in the inner function";
            console.log(outerVar); // outerVar에 접근
            console.log(innerVar); // innerVar에 접근
        }
    
        inner();
    }
    
    outer();

     

    동적(dynamic) 스코프 (권장하지 않음)

    함수를 호출한 시점에 스코프를 결정하는 방식을 의미한다.

    동적 스코프의 선언은 런타임 도중에 실행 컨텍스트나 호출 컨텐스트에 의해 결정된다.

     

    동적 스코프는 함수를 어디에서 호출했는지에 따라 스코프가 동적으로 결정되는 특성을 가지고 있다.

    이는 코드를 예측하기 어렵게 만들 수 있고, 디버깅이 어려워지며, 코드의 가독성이 떨어지는 등의 문제를 야기할 수 있다.

     

    아래는 JavaScript에서 동적 스코프를 시뮬레이션하는 간단한 예시이다.

    이 코드는 의도적으로 동적 스코프의 특성을 시연하기 위해 eval 함수를 사용하고 있다.

    eval은 문자열로 주어진 코드를 실행하는 함수로, 실행 시점에 동적으로 스코프를 결정할 수 있다.

    하지만 eval은 일반적으로 사용을 권장하지 않고 보안상의 이유로 피해야 한다.

     

    function dynamicScopeExample() {
        var x = "I'm in the global scope";
    
        function outer() {
            var x = "I'm in the outer function";
            eval("console.log(x)"); // eval 내부에서 x를 찾을 때, 동적 스코프로 검색
        }
    
        function inner() {
            var x = "I'm in the inner function";
            outer();
        }
    
        inner();
    }
    
    dynamicScopeExample();
    
    
    // 결과는 "I'm in the outer function"

     

    클로저

    자바스크립트는 동적 스코프를 직접적으로 지원하지 않지만 클로저를 통해 유사한 기능을 수행할 수 있다.

    클로저는 함수가 정의된 스코프를 기억해서 외부에서도 그 스코프의 변수를 사용할 수 있도록 한다. 

    function outer() {
        var outerVar = "I'm in the outer function";
    
        function inner() {
            console.log(outerVar); // 클로저를 통해 outerVar에 접근
        }
    
        return inner;
    }
    
    var closureFunction = outer();
    closureFunction(); // 출력: I'm in the outer function

     

    이 예시에서 inner 함수가 outer 함수 내에서 정의되었으며, outerVar에 접근할 수 있다.

    outer 함수가 호출된 이후에도 closureFunction을 통해 inner 함수가 호출되면 outerVar에 여전히 접근 가능하다.

     

    클로저를 통해 동적으로 스코프를 활용할 수 있지만, 이는 주로 함수가 정의된 위치의 렉시컬 스코프를 활용하는 방식이다.

    즉, 동적 스코프의 특성을 정적 스코프와 결합하여 사용할 수 있다.

     

    스코프 체인

    현재 스코프 레벨에서 변수를 찾을 수 없을 때 상위 스코프에서 찾는 걸 의미한다.

    안에서 밖쪽으로 단계적으로 찾아 나선다. ( 하위 -> 상위 -> 전체)

     

    스코프 레벨 별 구분 (Global,Local,Function,Block)

    전역 스코프 ( Global )

    전역으로 선언된 변수에 대해 접근과 조작이 가능한 유효한 범위

    // 전역 스코프(Global Scope) 변수 선언
    const globalVar = "I'm global!";
    
    function globalFunction() {
        console.log("Inside globalFunction:", globalVar);
    }
    
    // 전역 스코프에서의 변수 및 함수 접근
    console.log("Outside globalFunction:", globalVar);
    globalFunction();
    
    // 새로운 함수에서도 전역 변수에 접근 가능
    function anotherFunction() {
        console.log("Inside anotherFunction:", globalVar);
    }
    
    anotherFunction();

    지역 스코프 ( Local )

    함수 혹은 블록 내에서 접근과 조작이 가능한 유효한 범위

    함수 내에서 유효한 경우 함수 스코프, 블록 내에서 유효한 경우 블록 스코프

    function localScopeExample() {
        // 함수 스코프 변수
        var functionScopedVar = "I'm in a function scope!";
        console.log(functionScopedVar); // 함수 내에서 접근 가능
    
        if (true) {
            // 블록 스코프 변수
            let blockScopedVar = "I'm in a block scope!";
            console.log(blockScopedVar); // 블록 내에서 접근 가능
        }
    
        // console.log(blockScopedVar); // 에러: blockScopedVar는 블록 외부에서 접근할 수 없음
    }
    
    localScopeExample();

     

    함수 스코프 ( Function )

    선언한 변수가 함수 내에서 유효한 범위

    function functionScopeExample() {
        var localVar = "I'm in a function scope!";
        console.log(localVar); // 함수 내에서 접근 가능
    }
    
    // console.log(localVar); // 에러: localVar는 함수 밖에서 접근할 수 없음
    
    functionScopeExample();

    블록 스코프 ( Block )

    선언한 변수가 블록 내(중괄호)에서 유효한 범위

    function blockScopeExample() {
        if (true) {
            let blockVar = "I'm in a block scope!";
            console.log(blockVar); // 블록 내에서 접근 가능
        }
    
        // console.log(blockVar); // 에러: blockVar는 블록 밖에서 접근할 수 없음
    }
    
    blockScopeExample();

     

    호이스팅

    호이스팅(Hoisting)은 JavaScript에서 변수 및 함수 선언이 스코프의 최상단으로 끌어올려지는 동작을 말한다.

    이것은 코드에서 변수 및 함수를 선언하기 전에 해당 변수나 함수를 참조할 수 있다는 특징을 갖는다.

    다음은 변수와 함수 선언에서의 호이스팅 동작에 대한 간단한 예시이다.

     

    변수 호이스팅

    console.log(x); // undefined
    var x = 5;
    console.log(x); // 5

     

    위 코드는 이렇게 작동한다. 변수의 선언이 마치 끌어올려진 것 같이 작동을 한다.

    var x;
    console.log(x); // undefined
    x = 5;
    console.log(x); // 5

     

    x를 콘솔로 찍었을 때 아직 할당되지 않아 undefined로 나오는걸 볼 수 있다.

     

    주의사항: 호이스팅은 선언(Declaration)을 끌어올리지만, 할당(Initialization)은 끌어올리지 않는다.

    따라서 변수는 선언은 호이스팅되지만, 할당되기 전까지는 undefined로 초기화된다.

     

    함수 호이스팅

    foo(); // "Hello, I'm foo!"
    function foo() {
      console.log("Hello, I'm foo!");
    }

     

    함수 foo가 선언되기 전에 foo()를 호출했을 때도 정상적으로 동작한다. 함수 선언이 스코프의 최상단으로 끌어올려지기 때문이다.

     

    위 코드는 이렇게 작동한다.

    function foo() {
      console.log("Hello, I'm foo!");
    }
    foo(); // "Hello, I'm foo!"

     

    함수 선언은 함수 전체가 끌어올려지므로 함수 내부의 코드도 함께 끌어올려진다.

     

    호이스팅을 이해하면 코드 작성 시 순서에 따른 영향을 줄일 수 있으나,

    코드의 가독성을 높이기 위해 변수와 함수 선언은 스코프의 최상단에서 명시적으로 하는 것이 좋다.

    this

     

     

     

     

    728x90
    728x90