(JS) Scope

Mirrer·2022년 5월 3일
0

JavaScript

목록 보기
19/24
post-thumbnail

스코프 (Scope)

현재 실행되는 컨텍스트

Scope란 현재 실행되는 컨텍스트이며 변수를 참조할 수 있는 유효한 범위를 뜻한다.

스코프는 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다.

스코프를 정리하면 다음과 같다.


  • 변수를 참조할 수 있는 유효한 범위

  • 식별자(변수, 함수, 클래스 이름)가 유효한 범위

  • 블럭 안의 변수는 블럭 안에서만 유효


Code Block

Code Block은 변수의 유효 범위 영역이다.

예를들어 코드의 { }, if() { }, for() { }, function() { }....등등을 뜻한다.

블럭 외부에서는 블럭 내부의 변수를 참조할 수 없다.

{
  const a = 'a';
  console.log(a); // a
}
console.log(a); // Error

또한 함수 외부에서는 함수 내부의 변수, 매개변수를 참조 할 수 없다.

function print() {
  const message = 'Hello World'
  console.log(message); // Hello World
}
console.log(message); // Error

function sum(a, b) {
  console.log(a, b);
}
console.log(a, b); // Error

Garbage Collection

사용하지 않는 원시값, 객체, 함수... 등을 찾아 삭제

C 언어같은 저수준 언어에서는 메모리 관리를 위해 malloc()free()를 사용하여 개발자가 직접 메모리를 관리한다.

반면, 자바스크립트는 객체가 생성되었을 때 자동으로 메모리를 할당하고 더 이상 필요하지 않을 때 Garbage Collection에 의해 자동으로 해제된다.

Garbage Collection주기적으로 오브젝트 참조여부를 확인하여 참조하고 있지 않다면 메모리에서 삭제한다.

메모리 관리

글로벌 변수는 앱이 종료될때까지 메모리에 유지된다.

그러므로 가급적 글로벌 변수의 사용을 금하되 변수는 필요한 블럭내에서만 사용하는 것을 권장한다.

// 글로벌 변수는 앱이 종료될때까지 계속 메모리에 유지
const global = 1;

{
  // 블럭 내부에서만 존재, 블럭이 끝나면 자동 소멸(GC)
  const local = 1;
}

function print() {
  // 함수 내부에서도 블럭안에 필요한 경우, 필요한 곳에서 변수 선언 및 사용
  if (true) {
    let temp = 0;
  }
}

Lexical Environtment

스크립트 전체, 실행중인 함수, 코드블록 등이 갖는 자신만의 스코프

각각의 블록은 렉시컬 환경(Lexical Environtment)이라는 내부 오브젝트를 포함하고 있다.

렉시컬 환경 오브젝트는 블록의 선언된 변수, 인접한 부모의 정보...등등 다양한 정보를 포함한다.

렉시컬 환경은 현재 블록에 정보를 담당하는 환경 레코드(Environment Record), 블록의 부모를 참조하는 외부 환경 참조 (Outer Lexical Environment Reference)로 구성되어 있다.


Scope Chain

스코프 체인(Scope Chain)은 선언된 블록들이 부모의 렉시컬환경을 참조하는 것을 뜻한다.

기본적으로 블록은 종료되면 순서대로 실행 컨텍스트 스택에서 제거된다.

이 때 블록에서 사용하고자 하는 변수가 선언되있지 않다면 스코프 체인으로 연결된 부모 환경 레코드를 확인한다.

만약 스코프체인을 통해 변수를 자주 접근한다면 성능에 악영향을 준다.



Hoisting

선언된 코드를 최상단으로 끌어 올림

호이스팅(Hoisting)은 사전적 의미로 끌어 올리다라는 뜻이다.

자바스크립트 엔진(번역기, Interpreter)은 코드를 실행하기 전 변수, 함수, 클래스의 선언문을 끌어 올린다.

이 때 선언과 초기화 단계는 분리되어 선언만 코드의 최상단으로 끌어 올려진다.


함수 호이스팅

함수 호이스팅을 통해 함수의 선언문은 코드 최상단으로 끌어 올려져 함수 선언이전에도 호출을 가능하게 해준다.

함수 표현식은 호출이 불가능하다.

print1(); // hello

function print1() {
  console.log('hello');
}

print2(); // Error

const print2 = function print() {
  console.log('hello');
}

변수, 클래스 호이스팅

변수(let, const)와 클래스는 선언만 호이스팅되고 초기화는 되지 않는다.

그래서 초기화 전 변수에 접근하면 컴파일 에러가 발생한다.

console.log(hi); // Error
let hi = 'hi';

const cat = new Cat(); // Error
class Cat {};

var 변수

기본적으로 자바스크립트에서 변수를 선언할 때는 let, const키워드를 사용한다.

하지만 es6이전에는 주로 var키워드를 사용해 변수를 선언했다.

지금은 사용되지 않지만 이전에 var키워드를 사용한 코드를 읽기 위해서는 var키워드의 특징은 알아두어야 한다.


  • var변수 선언 키워드 없이 선언 & 할당이 가능
// 선언, 재할당 구분 어려움
str = 'var';
console.log(str); // var
  • var__중복 선언**_이 가능
var str = 'var';
var str = 'var';

console.log(str); // var var
  • var블록 레벨 스코프를 무시하고 함수 레벨 스코프만 지원
var animal = 'panda';
{
  var animal = 'cat';
  {
    var animal = 'dog';
  }
}
console.log(animal); // dog

function example() {
  var dog = 'dog';
}

console.log(dog); // Error

strict mode

JavaScript 의 제한된 버전을 선택하여 암묵적인 "느슨한 모드(sloppy mode)" 를 해제하기 위한 방법

엄격 모드(strict mode)는 ES5에 추가된 키워드이다. 사용하고자 하는 곳에 'use strict';를 입력하여 사용한다.

엄격 모드는 자바스크립트가 묵인했던 에러들의 에러 메시지를 발생시킨다. 즉 엄격하게 문법을 검사를 하겠다는 의미다.

엄격 모드는 다음과 같은 특징이 존재한다.


  • 키워드 삭제 불가능
'use strict';

var x = 1;
delete x; // Error
  • 키워드 생략 불가능
'use strict';

function add(x) {
  var a = 2;
  b = a + x; // Error
}

add(1);
  • 함수 내부에서 this는 undefined을 출력
'use strict';

function add() {
  console.log(this); // undefined
}

add();
  • 변수 선언 키워드 생략 불가능
'use strict';

const arr = [1, 2, 3];
for (num of arr) { // num변수에 선언 키워드 생략해서 에러
  console.log(num);
}

참고 자료

스코프 - 용어 사전 | MDN
자바스크립트의 메모리 관리 - JavaScript | MDN
호이스팅 - 용어 사전 | MDN
Strict mode - JavaScript | MDN
모던 자바스크립트 Deep Dive
모던 JavaScript 튜토리얼

profile
memories Of A front-end web developer

0개의 댓글