[Javascript] Scope의 이해

김진성·2022년 9월 15일
0

Javascript

목록 보기
1/1

자바스크립트는 단순한 언어로 여겨져 왔다. 우리가 변수에 다른 타입을 넣어도 실행이 되기도 하고 변수의 범위가 다양하다는 인식이 있다. 그러나 코드를 작성하는 과정에서 전역과 지역 변수에 대한 이해가 없으면 추후 중복에 대한 오류로 인식하기가 어려운 경우가 존재한다. 그래서 우리는 자바스크립트를 사용할 때 변수가 어디서부터 어디까지 유효한지 그 유효한 범위를 잘 설정하여 사용할 필요가 있다. 그래서 스코프에 대한 이해가 먼저 필요하다.

스코프(Scope)란?

식별자 접근 규칙에 따른 유효 범위

  • 스코프의 정의는 "식별자 접근 규칙에 따른 유효 범위"이다.
  • 식별자(변수, 함수, 클래스)에 접근할 수 있는 범위가 존재한다.
  • 범위는 중괄호 또는 함수에 의해 나누어진다.
  • 각각을 Block Scope와 Function Scope로 나눠진다.
// test.js

var global_variable = "전역 변수";
function local() {
	let local_variable = "지역 변수";
  	
  	console.log(global_variable, local_variable);
}

local()
// console.log => "전역 변수""지역 변수"

console.log(global_variable, local_variable);
						  // ~~~~~~~~~~~~~~ 
						  // 지역 변수는 local() 함수 내에서만
						  // 오류가 발생을 하게 된다. 

위 예시처럼 우리는 범위에 따른 변수의 사용 위치를 잘 이해하고 사용해야 한다.

스코프의 주요 규칙

1. 안쪽 스코프에서 바깥쪽 스코프로 접근할 수 있지만 반대는 불가능하다.

  • 바깥쪽 스코프에서 선언한 식별자는 안쪽 스코프에서 사용 가능하다.
  • 반면, 안쪽에서 선언한 식별자는 바깥쪽 스코프에서는 사용할 수 없다.

2. 스코프는 중첩이 가능하다.

3. 전역 스코프와 지역 스코프

  • 가장 바깥쪽의 스코프를 전역 스코프(Global Scope)라고 부른다.
  • 전역이 아닌 다른 스코프는 전부 지역 스코프(Local Scope)이다.

4. 지역 변수는 전역 변수보다 우선순위가 더 높다.

  • 전역 스코프에서 선언한 변수는 전역 변수이다.
  • 지역 스코프에서 선언한 변수는 지역 변수이다.
  • 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.

스코프의 종류

  • 스코프는 대표적으로 블록 스코프와 함수 스코프가 있다.
  • 화살표 함수는 함수 스코프가 아니고 블록 스코프로 취급된다.

Block Scope

  • ES6 이전에는 자바스크립트는 Global Scope와 Funciton Scope만 존재하였다.
  • 그러나 ES6 이후 let, const를 통하여 Block Scope를 지원할 수 있게 되었다.
  • 블록 스코프란 중괄호 {} 안에 선언된 변수들로 외부 블록에서는 접근할 수 없는 요소이다.
{
  let x = 2;
}
// x는 여기서 사용될 수 없다. 
{
  var x = 2;
}
// x는 여기서 사용될 수 있다. 

Local Scope

  • 자바스크립트에서 선언된 변수는 함수 내에서 지역 변수가 된다.
// carName 사용 불가능

function myFunction() {
  let carName = "Volvo";
  // carName 사용 가능
}

// carName 사용 불가능
  • 지역 변수는 함수 스코프도 될 수 있다. 내부 함수로서 사용되는 것이다.

Function Scope

  • 자바스크립트는 각 함수가 새로운 스코프를 만들어낼 수 있다.
  • 함수 내부에서 정의된 변수는 외부에서 접근할 수 없다.
function myFunction() {
  var carName = "Volvo";   // Function Scope
}

스코프와 var, let, const 키워드

  • 변수 선언 키워드 세 가지의 "차이점" 그리고 "스코프 유효 범위"는 아래와 같다.

유효 범위, 값 재할당, 재선언

const 키워드

  • 유효 범위 : 블록 스코프 / 함수 스코프
  • 값 재할당 : 불가능
  • 재선언 : 불가능

let 키워드

  • 유효 범위 : 블록 스코프 / 함수 스코프
  • 값 재할당 : 가능
  • 재선언 : 불가능

var 키워드

  • 유효 범위 : 함수 스코프
  • 값 재할당 : 가능
  • 재선언 : 가능

블록 단위로 스코프를 구분했을 때, 훨씬 더 예측 가능한 코드를 작성할 수 있으므로 let 키워드의 사용이 권장된다.

전역 객체(window)의 이해

  • Window 객체는 only 브라우저에만 존재하는 객체이다.
  • 브라우저의 창을 의미하는 객체이다.
  • 따라서 함수 선언식으로 함수를 선언하거나 var 키워드로 변수를 선언하면 window 객체에 속해진다.
  • 예를 들어, var는 전역 적으로 선언되었으면 window의 변수로 사용이 가능하다.
var carName = "Volvo";
// window.carName 의 형태로 사용할 수 있다.
let carName = "Volvo";
// window.carName 의 형태로 사용할 수 없다.

1. 전역 변수는 최소화하기

  • 가장 바깥 스코프에 정의한 변수가 전역 변수로 어디서든 접근이 가능하다.
  • 전역 변수를 최소화하면 side effect(의도하지 않은 로직에 의해 문제 발생)을 줄일 수 있다.
  • 그런데 그러한 전역 변수를 심지어 var로 선언하는 경우 문제가 될 수 있다.
    • 전역 변수는 어디서나 접근이 가능하다.
    • var 키워드는 블록 스코프를 무시한다.
    • 재선언과 재할당을 할 수 있다.
    • 전역 변수를 var로 선언해서 브라우저의 내장 기능을 못하게 만들 수도 있다.

1) 전역 변수 객체를 하나 만들어 사용하기

let store = {};

store.food = {
	kind: "야식"
  	name: "야채 곱창" 
};

// 다른 파일
console.log(store.food.kind);

2) 즉시 실행 함수를 만들어 사용하기

  • 즉시 실행함수는 전역 변수를 만드는 것이 아니라 즉시 실행되고 사용하고 나서 전역에서 바로 사라진다.
(function() {
	let store = {};

    store.food = {
        kind: "야식"
        name: "야채 곱창" 
    };

    console.log(store.food.kind);
})();

console.log(store.food.kind); // 이 함수는 인식하지 못하고 에러를 반환한다.

2. 선언 없는 변수 할당 금지

  • 선언 없이 변수를 할당하면 해당 변수는 var로 선언한 전역 변수처럼 취급된다.
  • 실수를 방지하기 위해 Strict Mode를 사용할 수 있다.
    • Strict Mode는 브라우저가 엄격하게 작동하도록 만들어준다.
    • "선언 없는 변수 할당"의 경우도 에러로 판단해준다.
    • 적용하려면, js 파일 상단에 'use strict'라고 입력하면 된다. (따옴표 포함)

예제들

전역 변수와 지역 변수가 중복 선언된 경우

var a = "global";

function scope() {
	var a = "local";
  	console.log(a);
}

scope(); // local
console.log(a) // global

전역 영역에서는 전역 변수만이 참조 가능하고 함수 내 지역 영역에서는 전역과 지역 변수 모두 참조 가능하지만 변수명이 중복된 경우 지역 변수를 우선하여 참조하게 된다.

내부 함수의 경우

var x = 'global';

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

  function bar() {  // 내부함수
    console.log(x); // local
  }

  bar();
}

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

내부 함수에서는 자신을 포함하고 있는 함수가 먼저 우선시 되어 local을 반환하게 된다.

profile
https://medium.com/@jinsung1048 미디엄으로 이전하였습니다.

0개의 댓글