스코프란?

일반명사) 유효 범위

고유명사) 참조하려는 대상의 식별자를 찾아내기 위한 규칙

  • 변수는 어디에 저장되어 있는가?
  • 필요할 때 프로그램은 어떻게 변수를 찾는가?
  • 특정 장소에 변수를 저장하고 나중에 그 변수를 찾는데는 잘 정의된 규칙이 필요하다.
  • 이런 규칙을 “스코프(Scope)” 라고 한다.
  • 식별자 이름으로 변수를 찾기 위한 규칙의 집합

스코프는 크게 2가지로 구분할 수 있다.

전역 스코프 : 코드 어디서든 참조할 수 있는 스코프.

지역 스코프 : 함수 코드 블록이 만든 스코프로 함수 자신과 그 하위 함수에서만 참조할 수 있는

모든 변수는 반드시 스코프를 갖는다.

 

전역 변수 : 전역에서 선언된 변수이며 전역 스코프를 가지므로 코드 어디서든 참조할 수 있는 변수

지역 변수 : 지역 내에서 선언된 변수이며 지역 스코프를 가지므로 지역과 그 지역 내에서만 참조할 수 있는 변수

자바스크립트는 함수 레벨 스코프를 따른다.

함수 레벨 스코프 : 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효(참조 가능)하고 함수 외부에서는 유효하지 않다는(참조할 수 없는) 규칙이다.

 

예시) 전역 변수와 지역 변수의 식별자가 중복되는 경우

var scope = 'global';

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

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

함수 내 지역 영역에서는 전역 변수 및 지역 변수 모두 참조 가능하나 위의 예시와 같이 전역 변수와 지역 변수의 식별자가 중복되는 경우 지역 변수를 우선적으로 참조한다.

 

예시) 함수 내에 내부 함수가 존재하는 경우

var scope = 'global'; // 전역변수

function foo() {
  var scope = 'local'; // 지역변수
  console.log(scope); // 'local'

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

  bar();
}
foo();
console.log(scope); // 'global'

내부함수는 자신을 포함하고 있는 외부함수의 변수에 접근할 수 있다.

함수 bar 에서 참조하는 변수는 함수 foo 에서 선언된 지역 변수이다.

실행 컨텍스트스코프 체인에 의해 참조 순위에서 전역 변수 scope 가 밀려났기 때문이다.

 

예시) 함수 내 영역에서 전역 변수에 접근

var number = 10;

function foo() {
  number = 60;
  console.log(number); // 60
}
// number = 10;
foo();
// number = 60;
console.log(number); // 60 

함수 영역에서 전역 변수를 참조할 수 있으므로 전역 변수의 값을 변경할 수 있다. 또한 내부 함수의 경우 전역 변수는 물론 상위 함수에서 선언된 변수에 참조/변경이 가능하다.

 

예시) 중첩 스코프

var number = 10; // 전역변수

function foo(){
  var number = 60; // 지역변수
  console.log(number); // 60

  function bar(){   // 내부함수
    number = 1000;
    console.log(number); // 1000
  }
  // number = 60;
  bar();
  // number = 1000;
}
// number = 10;
foo();
// number = 10;
console.log(number); // 10

중첩 스코프는 가장 인접한 지역을 우선하여 참조한다.

자바스크립트에서 변수 선언 시 스코프는 다음과 같이 결정된다.

var 로 선언된 변수는 선언된 위치에 따라 전역 변수 스코프 혹은 함수 레벨 스코프를 가진다.

var 로 변수 선언 시 전역 변수를 남발하게 하는 문제를 야기시킬 수 있다.

  • 전역 변수의 사용은 변수 이름이 중복될 수도 있다.
  • 또한, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만든다.

ECMAScript6 에서 도입된 let, const 로 선언된 변수는 선언된 위치에 따라 전역 변수 스코프 혹은 블록 레벨 스코프를 가진다.

자바스크립트에서는 렉시컬 스코프 방식으로 함수의 상위 스코프를 결정한다.

정적 스코프 또는 렉시컬 스코프 : 함수를 어디서 선언하였는지에 따라 함수의 상위 스코프를 결정한다.

함수를 선언한 시점에 함수의 상위 스코프가 결정되며 함수를 어디서 호출하였는지는 스코프 결정에 아무런 영향을 미치지 않는다.

 

예시)

var x = 1;

// abc 함수 선언
function abc() {
  var x = 10;
  defg();
}

// defg 함수 선언
function defg() {
  console.log(x);
}

abc(); // abc 함수 호출
defg(); // defg 함수 호출

// 출력 결과
// 1
// 1

abc 함수와 defg 함수는 모두 전역에 선언되어 있으며 선언 시점에 상위 스코프가 결정되는데 상위 스코프는 바로 전역이다.

전역 변수의 값 1 을 두 번 출력한다.

 

스코프 체이닝

스코프 체이닝은 변수를 검색하는 메커니즘(방식)이다.

LHS 와 RHS 참조 검색은 모두 현재 실행 중인 스코프에서 시작한다.

그리고 필요하다면(대상 변수를 찾지 못했을 경우) 한 번에 한 스코프씩 중첩 스코프의 상위 스코프로 넘어가며 식별자를 찾는다.

이 작업은 글로벌 스코프에 이를 때까지 계속하고, 대상을 찾았든 못 찾았든 작업을 중단한다.

주의)

RHS 참조가 대상을 찾지 못하면 ReferenceError 가 발생한다.

LHS 참조가 대상을 찾지 못하면 자동적, 암시적으로 글로벌 스코프에 같은 이름의 새로운 변수가 생성된다.

참고) RHS 검색과 LHS 검색

변수를 검색하는 이유는 변수에 값을 대입하거나(LHS 참조) 변수의 값을 얻어오기 위해서이다.(RHS 참조)

RHS(Right-hand Side) 검색

변수가 대입 연산자의 오른쪽에 있을 때 수행하는 검색 방식이다.

단순히 특정 변수의 값을 찾는 작업을 수행한다.

예시)

console.log(a);
  • console.log(...) 가 실행되려면 참조가 필요한데, console 객체를 RHS 검색하여 log 메서드가 있는지 확인한다.
    • 인수로 a 값을 전달하려면 참조가 필요한데, 변수 a 에 대해 RHS 검색을 통해 값을 찾는다.
  • “가서 console 객체를 먼저 찾아보고 console 객체를 찾았다면 console 객체 내에 log 메서드가 있는지 보고 찾아서 내게 가져와라” 라는 뜻이다.

LHS(Left-hand Side) 검색

변수가 대입 연산자의 왼쪽에 있을 때 수행하는 검색 방식이다.

값을 넣어야 하므로 변수 컨테이너 자체를 찾는 작업을 수행한다.

예시)

a = 2;

‘=2’ 대입 연산을 수행할 대상 변수를 찾는다.

 

참조

https://poiemaweb.com/js-scope 

복사했습니다!