1. 전역변수

  • 전역변수란 프로그램 전체에서 접근할 수 있는 변수이다. 글로벌 스코프를 갖는 변수라고도 할 수 있겠다.
  • 프로젝트 어디에서든 접근하여 참조, 할당, 재할당 할 수 있다.

  • 전역변수의 생성

    • 함수 밖에서 var 키워드를 통해서 선언된 변수
    • 함수 밖에서 키워드 없이 값을 할당받은 변수
    • 함수 안에서 키워드 없이 값을 할당받은 변수
  • 예시
    var a = 'global scope';
    b = 'global scope';
    function func() {
      c = 'global scope'
      var d = 'local scope'
    }
    
    func();
    
    console.log(a); // 'global scope'
    console.log(b); // 'global scope'
    console.log(c); // 'global scope'
    console.log(d); // 'ReferenceError: d is not defined at <anonymous>:14:13
    
    • 위 예제에서 a, b, c 는 글로벌 스코프를 갖는다. (정확하게 b, c 는 전역 변수가아닌 전역 객체의 프로퍼티다.)
  • var 키워드로 생성된 변수는 함수 안에서 선언된 경우를 제외하고 모두 전역변수로 할당된다.


2. 전역변수의 문제점

문제점

1. 결합과 중복 선언

  • 모든 전역변수들은 암묵적으로 결합되어있다.
  • 이런 경우에는 사용되고 있던 전역 변수가 쉽게 수정될 수 있고, 비슷한 이름으로 할당 될 수 있으며, 같은 이름으로 재할당 될 수 있다는 문제점이 있다.
  • 변수가 어디서 어떻게 변경되었는지 추적이 안된다면 디버그 또한 어려워진다.

2. 네임스페이스 오염

  • 자바스크립트의 전역 스코프는 파일을 분리해서 작성하더라도 모두 똑같은 전역 스코프를 공유한다.
  • 이렇게 될 경우에는 다른 파일에서 선언한 전역변수를 또 다른 파일에서 수정 되며, 우리가 예상하고 사용한 변수와는 다른 결과를 가져오게 될 수 있다.

3. 생명 주기

  • 변수의 생명주기는 해당 변수의 유효범위와 같다. 즉, 함수 안에서 선언한 var 변수의 생명주기는 함수가 호출되고 실행되는 주기와 똑같다.
  • 그런데 전역 변수의 경우에는 전역에 선언되었기 때문에 프로젝트가 실행되는 동안 생명주기가 계속 이어진다.
  • 생명 주기가 길어지면 변수에 접근하고 재할당 할 수 있는 가능성 또한 커진다는 것을 의미한다.

4. 스코프 체인

  • 자바스크립트는 스코프 안에서 참조한 변수 또는 함수가 없는경우 상위 스코프를 검색하는 스코프 체인을 가지고 있다.
  • 전역 변수의 경우에는 스코프 체인의 가장 상위에 존재하게 되며 코드를 실행햇을때 변수를 검색하는


3. 전역변수의 문제점 해결 방법

  • 스코프로 묶어준다.
  • let, const 등 다른 키워드로 변수를 선언한다.
  • 함수 안에서만 사용할 수 있는 변수를 선언하여 변수의 주기를 짧게 한다.

1. Name Space Object

  • 전역에 해당하는 객체를 하나 만들어서 네임스페이스를 만들어준다.
  • 이렇게 관리하게되면 변수나 함수의 이름이 중첩되거나 변형되는 것을 방지한다.
  • 네임 스페이스 구역 안에 다른 네임스페이스를 생성해줄수도 있다.

  • 예시
    var obj = {
      name: 'name',
      func() {
        return `hello, my name is ${this.name}.`
      }
    }
    
    obj.birth = 0422
    obj.birth.month = 4
    obj.birth.day = 22
    


(아래 설명하는 IIFE 와 Module Pattern은 closure와 매우 비슷해 보인다. 실제로 Module Pattern은 클로저를 기반으로 작동한다는 것을 기억하자!)

2. IIFE

  • immediately invoked function expression 의 약자로 정의와 실행이 함께 일어나는 즉시 실행 함수이다.
  • 함수를 선언과 동시에 즉시 실행하여 함수의 지역을 생성하고, 함수 안에 선언된 변수들은 함수의 지역안에 생성된 지역변수가 된다.
  • 외부에서는 함수 안의 변수에 접근할 수 없으며, 변수의 중첩, 재할당등 전역변수의 문제를 피해갈 수 있다.

  • 예시
    (example = function () {
      var myName = 'Tony'
      return myName
    })()
    
    example()  // 'Tony'
    myName  //  ReferenceError: myName is not defined
    


3. Module Pattern

  • module pattern이란?

    • 즉시 실행 함수로 감싸 지역을 만들고 그 안에 클래스를 넣은 것이라고 생각하면 된다.
    • 클로저의 기능중 하나라고 생각해도 될것 같다.
    • 만약 클로저를 모른다면 스코프를 생성하고 전역 변수를 방지하는 차원에서만 알고 넘어가면 좋을 것 같다.
  • 예시

    var counter = (function() {
      var number = 0; // 클로저로 인해서 전역변수가 아닌 지역변수가 되며 외부에서는 접근할 수 없다.
    
      return function () {  // 외부로 공개할 함수나 메서드나 객체, 변수를 반환해준다.
        return ++number;
      }
    }());
    
    console.log(counter())  // 1
    console.log(counter())  // 2
    console.log(counter())  // 3
    console.log(counter.number)  // undefined
    


4. ES6 Module

  • 기존에 javascript에서는 지원되지 않던 모듈 기능을 추가한 것이다.
  • 아직까지는 Chrome 61, FF 60, SF 10.1, Edge 16 이상 정도에서 지원한다고 한다.
  • ES6 Module을 사용하면 var 키워드는 전역 키워드가 되지 않으며 하나의 script파일을 하나의 스코프를 갖을 수 있게 된다.

  • 사용방법

    • script 태그를 추가할때 type=”module”로 지정하여 추가해주고, javascript의 파일 확장자 명은 mjs로 지정해준다.
    • 파일 확장자명을 mjs로 하지 않아도 되지만 ECMAScript에서 권장하고 있기 때문에 되도록이면 mjs로 해주자

    • 예시
      <script type='module' src='test.mjs'></script>
      <script type='module' src='ES6ModuleTest.mjs'></script>
      
  • 몇몇의 구형 브라우저에서는 지원되지 않는 기능이라서 잘 살펴보고 사용해야한다.

5. let, const 키워드

  • 드디어 우리에게 익숙한 키워드가 나왔다.
  • ES6부터 도입된 let, const는 이미 프로젝트를 몇 번 해본 사람이거나 공부를 좀 한 사람이라면 당연스럽게 사용하고 있는 키워드이다.
  • var를 대체하기 위해 만들어 진 키워드이며 var와 똑같이 변수, 함수, 객체 등을 선언할때 사용한다.

    1. let

      • var와는 다르게 let은 중복 선언이 되지 않는다.
      • 변수 호이스팅이 되긴 하지만 변수 선언 시점보다 먼저 참조하면 ReferenceError가 발생하게 된다.
      • 전역 변수로 선언되더라도 전역 객체의 프로퍼티로 존재하지 않는다.
      • let은 var처럼 재할당이 가능하다.
      • 함수 뿐만 아니라 모든 블록 스코프 안에서만 유효하도록 되어있다.

      • 예제
        let number = 24;
        
        {
          let number = 33;
          let name = 'summer';
          console.log(number);  // 33 출력
        }
        
        console.log(number);  // 24 출력
        
        number = 95;
        console.log(number);  // 95 출력
        
    2. const

      • let과는 다르게 중복W 선언이 되지 않는다.
      • 중복 선언이 되지 않으므로 상수를 선언할때 사용된다.
      • 함수 뿐만 아니라 모든 블록 스코프 안에서만 유효하도록 되어있다.
      • const로 객체 선언 시, 객체의 프로퍼티는 생성, 변경, 삭제 등이 가능하다.

      • 선언 예제

        const number = 24;
        
        {
          const number = 33;
          const name = 'summer'
          console.log(number);  // 33 출력
        }
        
        console.log(number);  // 24 출력
        
        number = 95;  // TypeError: Assignment to constant variable.
        
      • 상수 예제
      • 상수는 항상 스네이크케이스로 대문자를 써서 선언해준다.

        // 좋은 예제는 아니니 참고만..
        
        let user = '학생';
        const STUDENT = '학생';
        
        if ( user === STUDENT ) {
          console.log('학생입니다.')
        } else {
          console.log('학생이 아니면 이용할 수 없습니다.')
        }
        

1 ~ 5 번의 기능의 차이점

  • 읽어내려오면서 느꼈겠지만 1번에서부터 5번으로 흘러오는 동안 조금씩 더 간결하고 유용한 방법들이 나온것을 알 수 있다.
  • 그냥 보기만해도 let, const 키워드를 상황에 맞게 사용해주는 것이 가장 간단하고 쉬워보인다.
    • let과 const는 각각의 특성이 있으므로 상황에 따라서 다르게 사용해주면 된다.
    • 기본적으로 const를 사용하여 변수의 중복과 재할당을 방지해주고 재할당이 되어야하는 경우에는 let을 사용해주자.
  • 그리고 그 다임이 ES6 Module인데 아직까지는 많은 브라우저에서 지원해주는 것이 아니라서 사용하기 조금 조심스러워 보인다.
  • 클로저를 잘 알고, 메모리에대해서도 충분한 이해가 있다면 Module Pattern을 사용하는 것도 좋다.
    • Module Pattern을 사용하여 함부로 수정되면 안되는 데이터는 숨겨주어 데이터를 관리할 수 있다.
  • 그 외에는 때에따라서 적절히 사용해주면 될 것 으로 보인다.