본문 바로가기
Programming Language

JS33 - 06.함수 범위, 블록 범위, 렉시컬(lexical) 범위

by 양찬우 2021. 5. 31.
728x90

함수 스코프는 모든 변수가 함수에 속한다는 개념을 가진다. 따라서 함수 전체에서 사용/재사용이 가능하다.(실제로 중첩 된 스코프에서도 접근 할 수 있음). 이는 매우 유용하기에, Javascript 변수의 “동적(dynamic)” 특성을 최대한 활용하여 필요에 따라 다른 유형의 값을 취할 수 있다.

기본 스코프에서의 숨김 (Hiding In Plain Scope)

  • 스코프-기반의 숨김을 사용하는데에는 여러 가지 이유가 있다. 소프트웨어 디자인 원칙 “최소 특권의 원칙”[최저 권한]의 이유인데, “최소 권한”또는 “최소 노출”이라고도 한다. 이 원칙은 모듈/객체를 위한 API 처럼 소프트웨어 설계에서 최소한 필요한 것만 노출하고 다른 모든 것을 “숨겨야”한다고 명시한다.
  • 이 원칙은 변수와 함수를 포함할 스코프를 선택하는 데까지 확장된다. 모든 변수와 함수가 전역 스코프에 있다면, 어떤 중첩된 스코프 범위에서도 접근할 수 있을 것이다. 하지만 이건 비공개로 유지되어야할 많은 변수/함수를 노출하므로, 변수/함수가 올바르게 사용되는 것을 저해하기에 “최저원칙”을 위반한다.
  • 충돌 방지전역 “네임스페이스” (Global “Namespaces”)그러한 라이브러리는 일반적으로 글로벌 스코프에서 충돌할 위험이 없는 고유한 이름을 가진 단일 변수 선언(객체)을 생성한다. 그런 다음 객체는 해당 라이브러리의 “네임스페이스”로 사용되며, 여기서 모든 기능의 노출은 해당 객체(네임스페이스)의 속성으로 이루어진다.
  • 특히 변수의 충돌은 주로 글로벌 스코프에서 발생한다. 프로그램에 로드 된 여러 라이브러리는 내부/private 함수 및 변수를 제대로 숨기지 않으면 서로 쉽게 충돌할 수 있다.
  • 스코프 내에서 변수와 기능을 “숨기는” 또 다른 장점은 이름이 같지만 용도가 다른 두 개의 다른 식별자 사이에 의도하지 않은 충돌을 방지하는 것이다. 충돌은 종종 예상치 못한 값의 덮어쓰기를 초래한다.

스코프란?

자바스크립트에서 어떤 변수에 접근할 수 있는지==변수의 유효범위를 정의한다.

변수에 접근할 수 있는 범위

스코프를 사용하는 이유

최소 접근의 원리. 불필요한 접근을 막는다.

스코프는 1. 버그를 추적하는 시간을 줄이고 2. 네이밍 문제를 해결할 수 있다.

전역Global 스코프

함수 바깥이나 {} 바깥에서 선언되었다면 전역 스코프에 정의된다.

하나의 자바스크립트 문서 → 하나의 전역 스코프

전역변수로 선언하면 코드 모든 곳에서 사용할 수 있다. 함수 내에서도 사용 가능하다.

이름이 충돌하거나 변수를 덮어쓸 수 있으므로 사용하지 않는 것이 좋다.

지역Local 스코프

코드의 특정 부분에서만 사용이 가능하다.

함수 스코프

함수를 선언할 때마다 새로운 스코프가 생성된다.

함수 내부에서 변수를 선언한다면, 선언한 함수 내에서만 변수를 사용할 수 있다.

  • 함수 호이스팅과 스코프

함수는 서로의 스코프에 접근할 수 없다. 어떤 함수를 다른 함수에서 사용할 경우에도 마찬가지이다.

블록 스코프

{ } 내에서 선언한다면, 변수는 이 중괄호 블록 내부에서만 사용 가능하다.

if, for, while 같은 조건문, 반복문이 여기에 해당된다.

함수를 선언할 때 블록을 사용해야 하므로, (화살표 함수를 쓰는 게 아니라면) 블록 스코프는 함수 스코프의 서브셋이다.

  • var 는 블록 스코프를 생성하지 않는다. (함수 스코프만)
  • let const 는 지역 스코프를 생성한다.
  • == 블록 스코프의 일관성을 유지할 수 있다.
  • IIFE 를 사용하여 함수에 인자를 전달하는 방법으로도 스코프를 생성할 수 있다.

렉시컬Lexical 스코프

렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지를 따른다.

== 함수를 선언하는 시점에서 상위 스코프가 결정된다.

var x = 1;

function foo() {
  var x = 10; // 그림자 식별자
  bar();
}

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

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

네스팅된 스코프Nested scopes

함수가 다른 함수 내부에서 정의되었다면, 내부 함수는 외부 함수의 변수에 접근할 수 있다.

하지만, 외부 함수는 내부 함수의 변수에 접근할 수 없다. → private 변수

function outerFunction () {
  const outer = 'I’m the outer function!'
    
  function innerFunction() {
     const inner = 'I’m the inner function!'
     console.log(outer) // I’m the outer function!
  }
    
  console.log(inner) // Error, inner is not defined
}
728x90

댓글