Javascript 스코프(Scope)의 개념 / var, let, const 키워드, window 객체
Code/JavaScript

Javascript 스코프(Scope)의 개념 / var, let, const 키워드, window 객체

반응형

Scope : 변수 접근 규칙에 따른 유효 범위

 

변수는 어떠한 환경 내에서만 사용 가능하며, 프로그래밍 언어는 각각의 변수 접근 규칙을 갖고 있다.

변수와 그 값이, 어디서부터 어디까지 유효한 지를 판단하는 범위이다.

Javascirpt는 기본적으로, 함수가 선언되는(lexical) 동시에 자신만의 Scope를 가진다.

 

let greeting = 'Hello';
function greetSomeone() {
  let firstName = 'Josh';
  return greeting + ' ' + firstName;
}

greetSomeone(); // 'Hello Josh'
firstName; // ReferenceError

 

 

 

함수 내에 선언된 firstName 변수를 함수 밖에서 호출을 시도했더니 참조 에러가 발생한다.

그 이유는?

 

스코프의 범위

- 변수 firstName에 접근할 수 있는 범위가 존재하고 있다.

- Local Scope 안쪽에서 선언된 변수는 밖에서 사용할 수 없다.

 

Local Scope vs Global Scope

-안쪽 Scope에서 바깥 변수/함수에 접근하는 것은 가능하나, 바깥쪽 Scope에서 안쪽 변수/함수에 접근하는 것은 불가하다.

-Scope는 중첩이 가능하다. 함수 안에 함수를 넣을 수 있다.

-Global Scope는 최상단의 Scope로, 전역 변수는 어디서든 접근이 가능하다.

-지역 변수는 함수 내에서 전역 변수보다 더 높은 우선순위를 가진다.

 

let name = "Richard";

function showName() {
  let name = "Jack"; // 지역 변수
  // showName 함수 안에서만 접근 가능
  console.log(name); //  Jack
}

console.log(name); //첫번째 Richard
showName();        //두번째
console.log(name); //세번째 Richard

 

상기 코드가 콘솔에 출력되는 결과는 Richard, Jack, Richard 이다. 

 

let name = "Richard";

function showName() {
  name = "Jack"; // 전역 변수
  // 선언(let)이 없기 떄문에, 바깥 scope에 있는 name이라는 변수를 가져온다.
  console.log(name); //  Jack
}

console.log(name); //첫번째 Richard
showName();        
console.log(name); //세번째 Jack

 

상기 코드는, showName 항수 속 name변수가 전역 변수로 취급되면서 name이라는 변수에 새로운 값을 할당한 것과 동일하다고 생각하면 된다. 고로, 세번째 콘솔 출력 글자는 name = 'Jack' 과 동일한 것이다.

 

Function Scope vs Block Scope

Block Scope  : 중괄호로 시작하고, 끝나는 단위

 

for (let i=0; i<5; i++) {
  console.log(i); // 다섯번 iteration
}
console.log('final i', i); // ReferenceError

 

block 범위를 벗어나는 즉시 변수를 사용할 수 없다.

 

var 키워드 vs let 키워드

변수를 정의하는 또 다른 키워드는 var 가 있다.

- JacaScript는 기본적으로, 함수 단위로 자신만의 Scope를 가진다. -> var 키워드 (old way)

- 그러나, Block 단위로 Scope를 구분했을 때에 예측하기 쉬운 코드를 작성할 수 있다. -> let 키워드

 

for (var i=0; i<5; i++) {
  console.log(i); // 다섯번 iteration
}
console.log('final i', i); // 5

 

block 범위를 벗어나도, var키워드를 사용할 경우 같은 function scope 에서는 사용 가능하다.

 

크롬 개발자 콘솔을 통해 var키워드와 let 키워드를 확인해보자.

(Function Scope 와 Block Scope의 차이 확인)

 

function greetSomeone(firstName) {
  var time = 'night';
  if(time === 'night') {
    var greeting = 'Good Night';
  }
  
  return greeting + ' ' + firstName;
}

greetSomeone('Steve');
function greetSomeone(firstName) {
  let time = 'night';
  if(time === 'night') {
    let greeting = 'Good Night';
  }
  
  return greeting + ' ' + firstName;
}

greetSomeone('Steve');

 

var 키워드 사용 디버깅

 

var 키워드를 사용했을 때, 우측 Scope창에는 두 종류의 Scope (Local, Global)가 존재한다.

Local Scope에는 (this값을 제외하고) 세 개의 변수가 담겨있다. (firstName, greeting, time)

함수 안에 정의된 모든 변수를 Local Scope에서 사용 가능하다.

 

 

let 키워드 사용 디버깅

 

let 키워드를 사용했을 때, Local Scope에 var키워드 사용시와는 다르게 greeting 변수가 보이지 않는다.

greeting 변수가 없으므로, 리턴문에서 ReferenceError가 발생한다.

greeting 변수는 해당 block 안쪽에서만 접근 가능한 것을 알 수 있다.

 

const 키워드

값이 변하지 않는 변수, 즉 상수를 정의할 때 사용하는 키워드이다.

 

- let 키워드와 동일하게 Block Scope를 따른다.

- 값 재정의를 시도할 경우, TypeError가 발생한다. (재정의 불가)

 

const 상수 값 재정의 시도시 에러
키워드 별 정리

 

전역 변수와 window 객체

window는 전역 범위를 대표하는 객체이다.

Global Scope에서 선언된 함수, 그리고 var 키워드를 이용해 선언된 변수는 window 객체와 연결된다.

 

var myName = "Paul";
console.log(window.myName); // Paul

function foo() {
  console.log('bar');
}

console.log(foo === window.foo); // true

 

전역 범위에 너무 많은 변수를 선언하지 않도록 주의해야 한다.

 

선언 없이 초기화된 전역 변수

function showAge() {
  // age는 전역 변수로 취급된다
  age = 90;
  console.log(age);
}
showAge(); // 90
console.log(age); // 90

 

선언 키워드 (var, let, const) 없이 변수를 초기화 할 경우 전역변수로 취급되기 때문에 항상 주의해야한다.

 

'use strict';

function showAge() {
  age = 90; // 여기서 에러 발생
  console.log(age);
}
showAge(); // 90
console.log(age); // 90

 

이런 실수를 방지하고 싶은 경우, 위와 같이 Strict Mode 를 적용하여 문법적으로 실수할 수 있는 부분들을 에러로 확인할 수 있다.

반응형