JavaScript

[JavaScript] Scope(스코프), Closure(클로저), var

SangRok Jung 2022. 4. 16. 00:51
반응형

Scope (스코프)

 

개념

변수가 유효성을 가지는 범위.

스코프는 기본적으로 프로세스 메모리 맵의 구조에 의존적.

선언된 위치에 따라 스코프가 결정된다.

같은 이름으로 변수가 선언된 경우 스코프가 겹칠 수 있다.

스코프가 겹칠 때 어떤 변수가 우선권을 가지는지 판단하는 기능이 필요하며 이러한 기능을 식별자 결정(identifier resolution)이라고 한다.

 

 

 

종류

구분 전역 스코프 지역 스코프
변수의 의미 전역변수 지역 변수
선언위치 코드의 가장 바깥 부분 함수의 내부
유효영역 전역 영역과 그 하위 영역 함수 자신과 그 하위 영역
특징 Var와 같은 선언자를 생략시 전역 스코프 - ES5(var)는 함수 레벨 스코프 지원
- ES6(let, const)는 블록 레벨 스코프 지원

** 블록 레벨 스코프스코프 : C++, JAVA 언어 등에서 지원하는 스코프. if, for, try/catch 등이 스코프 영역으로 판단된다.

 

 

 

 

식별자 결정

식별자 결정은 가장 가까운 스코프를 우선으로 한다.

<body>
    <script>
        const sc = 'global'

        function func()
        {
            console.log(sc);
        }

        func()

        //global

        function func2()
        {   
            const sc = 'local'
            console.log(sc);
        }

        func2()

        //local
    </script>
</body>

 

 

▷ 함수 레벨 스코프

1. ES5 방식

- var 사용

- var 생략

- ES5의 var는 함수 레벨 스코프를 가진다. 즉 함수 내에서 유효하다.

 

2. ES6 방식

- const : 값을 바꿀 수 없다.

- let : 값을 바꿀 수 있다.

- ES6의 const나 let은 블록 레벨 스코프를 가진다.  즉 블록 내에서만 유효하다.

 

<body>
    <script>
        function func()
        {
            for (var i = 0; i < 5; i++)
            {
                i;
            }
            console.log(i);
        }
        func()
        //5

        function func2()
        {
            for (let i = 0; i < 5; i++)
            {
                i;
            }
            console.log(i);
        }
        func2()
        //Uncaught ReferenceError: i is not defined

    </script>
</body>

 

 

 

▷ 식별자 결정 시

Javascript는 변수 선언 없이 변수를 사용할 수 있다. →  var로 해석

var는 Hoisting에 적용되어 식별된다.

<body>
    <script>
        function func()
        {
            sc1 = 'local' //var로 해석함
            console.log(sc1);
        }
        func()
        //loacl


        let sc2 = 'global'

        function func2()
        {
            sc2 = 'loacl' //var로 해석하여 전역변수에 입력함
            console.log(sc2);
        }
        func2()
        console.log(sc2)
        //local
        //local

    </script>
</body>

 

 

var를 사용할 시 문제점

  • 함수 레벨 스코프
  • Hoisting
  • 전역 영역 침범

= 코드를 읽기 어렵다.

 

 

 

▷ 식별자 결정의 난해함

아래 코드는 무한 루프가 발생한다.

  • f1()에서의 i는 for문에서 선언한 i를 초기화한다.
  • f1()에 i가 없기 때문에 스코프 체이닝으로 인하여 for문에 i를 참조한다.
<body>
    <script>
        function f1()
        {
            i = 0;
        }

        for (var i = 0; i < 10; i++)
        {
            f1();
        }

        //무한루프 발생
    </script>
</body>

* 스코프 체인

함수의 중첩 구조로 인해 스코프도 중첩 구조가 생긴다.

식별자 결정을 위해 가까운 스코프로부터 전역 스코프까지 계층적으로 연결된 구조를 스코프 체인이라고 한다.

<body>
    <script>
        let a = 30;

        const f1 = function()
        {
            let a = 10;
            const f2 = function()
            {
                let a = 10;
                console.log(a);
            }
            f2()
        }
        f1()

        //10
    </script>
</body>
<body>
    <script>
        let a = 30;

        const f1 = function()
        {
            let a = 10;
            const f2 = function()
            {
                console.log(a);
            }
            f2()
        }
        f1()

        //10
    </script>
</body>
<body>
    <script>
        let a = 30;

        const f1 = function()
        {
            const f2 = function()
            {
                console.log(a);
            }
            f2()
        }
        f1()

        //30
    </script>
</body>

 

 

 

 

 


 

 

 

 

 

Closure (클로저)

 

개념

내부 함수에서 외부 함수로 스코프 체이닝을 통해 외부 함수의 변수로 접근 가능한 함수의 조합.

내부 함수에서 전역 영역 범주.

자바스크립트 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어(Functional Programming language: 얼랭(Erlnag), 스칼라(Scala), 하스켈(Haskell), 리스프(Lisp)…)에서 사용되는 중요한 특성이다.

 

더보기

“A closure is the combination of a function and the lexical environment within which that function was declared.”
"클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다."

by. MDN

 

원인

스코프 체이닝

 

결과

클로저

 

내부 함수는 외부함수 변수에 접근 가능 (스코프 체이닝)

외부 함수는 내부 함수의 변수에 접근이 불가능.

 

 

 

활용

title지역변수는 외부에서 접근할 수 없음
클래스와 비슷한 구조로 활용
<body>
    <script>
        const makeInstance = function(title)
        {
            return {

                getTitle() //function 축약됨
                {
                    return title;
                },
                setTitle : function(_title)
                {
                    title = _title;
                }

            }
        }


        const book1 = makeInstance('title1');

        console.log(book1.getTitle());
        book1.setTitle('titl2')
        console.log(book1.getTitle());

        //title1
        //titl2
    </script>
</body>
 
 
 

 

 


 
 
 
 
 

var의 중복 선언

var의 중복 선언시 var를 생략한 것과 같은 효과가 발생한다.
프리미티브의 경우 메모리의 재할당이 이루어 진다.
 
 
중복 선언이 가능한 var
 
 
constlet은 이러한 중복 선언을 허용하지 않는다.

 

 

 

 

 

 

전역 변수(Global Variable)의 사용

 

전역 변수의 문제점

일반적으로 자바스크립트는 외부라이브러리의 의존도가 높고
따라서 전역변수 사용시 이름이 겹치는 경우 오류발생한다.
 

 

해결방안

전역 객체를 이용 = 사용할 전역 변수의 객체를 만들어서 사용.

필요한 모든 전역 변수들을 전역 객체의 속성으로 등록하여 사용.

즉시 호출 함수를 이용.

<body>
    <script>
        (function()
        {
            const myGolbal = {

                value1 : 1,
                array1 : [11, 22, 33, 44, 55]
            };

            const func = function()
            {
                return myGolbal.array1[0] + myGolbal.value1;
            }

            console.log(func());
        })()
        
        //12
    </script>
</body>

 

 

*파라미터 안의 변수는 let이 생략되어 있음
반응형