자바스크립트

[DeepDive]13~15장 스코프/전역 변수의 문제점/let,const 키워드와 블록 레벨 스코프

민ズl 2024. 10. 22. 21:38

✅13장 스코프

스코프란🤔

식별자가 유효한 범위
또는
자바스크립트 엔진이 식별자를 검색할 때 사용하는 규칙

*식별자 : 변수, 함수, 클래스의 이름

 

  • 스코프는 자바스크립트를 포함한 모든 프로그래밍 언어의 기본적이며 🌟중요한 개념🌟
    👻 자바스크립트의 스코프는 다른 언어의 스코프와 구별되는 특징이 있음
  • 변수, 함수와 깊은 관련이 있음
function add(x,y) {
   //매개변수는 함수 몸체 내부에서만 참조할 수 있다.
   //즉, 매개변수의 스코프(유효범위)는 함수 몸체 내부다.
   console.log(x,y); // 2  5
   return x + y;
}

add(2,5);

//매개변수는 함수 몸체 내부에서만 참조할 수 있다.
console.log(x, y) // ReferenceError : x is not defined
  • var 키워드로 선언한 변수의 스코프 (중복 허용⭕)
    💩증말 var는 똥이다!
function foo(){
   var x = 1;
   // var 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용
   // 아래 변수 선언문은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작
   var x = 2;
   console.log(x) //2
}
foo();
  • let,const 키워드로 선언한 변수의 스코프 (중복 불가❌)
function bar() {
   let x = 1;
   let x = 2; // error
}

스코프 특징🎈

  • 이름 충돌 방지
  • 메모리 절약

스코프 종류🎈

  • 전역 스코프 : 코드 어디에서든지 유효
  • 지역 스코프 : 자신의 지역 스코프와 하위 지역 스코프에서 유효
const text = 'global'; // 전역 변수, 전역 스코프 (글로벌 변수, 글로벌 스코프)
{
  const text = 'inside block1'; // 지역 변수(로컬변수), 지역 스코프(로컬스코프)
  {
    const text = 'inside block2';
    console.log(text); // inside block2
  }
}

스코프 체인🎈

  • 스코프가 계층적으로 연결된 것
  • 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조 가능
  • 하위 스코프에서 유효한 변수는 상위 스코프에서 참조 불가
    👉마치 부자 관계로 이뤄진 상속과 유사

모던 딥다이브 자바스크립트

함수 레벨 스코프

  • 자바스크립트는 함수 레벨 스코프를 사용
  • 함수 내에서 선언된 매개변수와 변수는 함수 외부에서는 ❌
var x = 'global';

function foo() {
  var x = 'local';
  console.log(x);
}

foo();          // local
console.log(x); // global

 

렉시컬 스코프

  • 함수를 어디에 선언하였는지에 따라 스코프를 결정
var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // 1
bar(); // 1

✅14장 전역 변수의 문제점

  • 변수는 자신이 선언된 위치에서 생성되고 소멸
    🚫함수 내부에서 선언된 지역 변수는 함수가 호출되면 생성되고, 함수가 종료하면 소멸
function foo() {
   var x = 'local';
   console.log(x); // local
   return x;
}

foo();
console.log(x); // error

모던 딥다이브 자바스크립트
모던 딥다이브 자바스크립트

  • 전역 변수의 무분별한 사용은 위험🚫
  • 변수의 스코프는 좁을수록 좋음👍

전역 변수의 사용을 억제할 수 있는 방법🤔

  • 즉시 실행 함수 (라이브러리에 자주 사용)
(function(){
   const foo = 10; // 즉시 실행 함수의 지역 변수
   ...
}())

console.log(foo); // error
  • 네임스페이스 객체 (그다지 유용하진 않음)
let MYAPP = {}; // 전역 네임스페이스 객체
MYAPP.name = 'Lee';
console.log(MYAPP.name); // Lee
  • 모듈 패턴 (정보 은닉 구현하기 위해 사용)
const Counter = (function(){
   // private 변수
   let num = 0;
   
   //외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환
   return {
      increase(){
         return ++num;
      }
   }
}()}

// private 변수는 외부로 노출되지 않음
console.log(Counter.num) // undefined

*캡슐화 : 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것

*정보은닉 : 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용

  • ES6 모듈 (구형 브라우저에서는 동작x)
<script type="module" src="app.js"></script>

✅15장 let,const 키워드와 블록 레벨 스코프

var 키워드로 선언한 변수의 문제점💩

  • 변수 중복 선언 허용
var x = 1;
var y = 1;
var x = 100; // 중복 선언을 허용
var y; // 초기화문이 없는 변수 선언문은 무시됨
  • 함수 레벨 스코프
var foo = 123; // 전역 변수

console.log(foo); // 123

{
  var foo = 456; // 전역 변수
}

console.log(foo); // 456
  • 변수 호이스팅
console.log(foo); // undefined
var foo;

console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar;

let 키워드💫

  • 변수 중복 선언 금지
let bar = 123;
let bar = 456; // error
  • 블록 레벨 스코프
let foo = 1; // 전역 변수

{
  console.log(foo); // ReferenceError: foo is not defined
  let foo = 2; // 지역 변수
}
  • 변수 호이스팅
// 스코프의 선두에서 선언 단계가 실행된다.
// 아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 없다.
console.log(foo); // ReferenceError: foo is not defined

let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

https://poiemaweb.com/es6-block-scope

const 키워드💫

  • 반드시 선언과 동시에 초기화해야 함
const FOO; // SyntaxError: Missing initializer in const declaration
  • 재할당 금지
const FOO = 123;
FOO = 456; // TypeError: Assignment to constant variable.
  • 일반적으로 상수의 이름은 대문자로 선언해 상수임을 명확히 나타냄
  • 여러 단어로 이뤄진 겨우에는 언더스코어(_)로 구분해서 스네이크 케이스로 표현하는것이 일반적
// 10의 의미를 알기 어렵기 때문에 가독성이 좋지 않다.
if (rows > 10) {
}

// 값의 의미를 명확히 기술하여 가독성이 향상되었다.
const MAXROWS = 10;
if (rows > MAXROWS) {
}
  • 변수에 원시 값을 할당한 경우 값 변경❌
  • 변수에 객체를 할당한 경우 값 변경⭕
const user = { name: 'Lee' };

// const 변수는 재할당이 금지된다.
// user = {}; // TypeError: Assignment to constant variable.

// 객체의 내용은 변경할 수 있다.
user.name = 'Kim';

console.log(user); // { name: 'Kim' }

 

∴ 변수 선언에는 기본적으로 const 사용, 재할당할때는 let 사용🌟