«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

방춘덕(고양이 키우면 지을 이름)의 개발 블로그입니다.

scope 본문

JS

scope

방춘덕 2019. 12. 13. 09:43

이 글을 원활하게 읽으려면 이전 글인 execution context 와 execution context stack과 execution context의 생성과정을 읽는 것을 권장한다.

 

목차

  1. scope란?
  2. global scope
  3. local scope
    1. 몇 가지 상황들
  4. non block level scope
  5. lexical scope

1). scope란?


scope는 런타임에서 함수, 변수, 객체등에 대한 접근성을 결정한다. 즉, scope는 참조하려는 식별자를 찾기 위한 규칙이다.
var a = 10

function A() {
  var b = 20
  console.log(a, b)
}

A()

JS는 이런 코드에서 식별자에 대한 접근을 어떻게 할까? scope가 바로 어디서 어떻게 식별자에 대해 접근하는지를 결정해준다.

 

만약함수 선언, 변수, 객체에 대한 접근 규칙을 결정하는 scope가 없다면, 사실상 모든 코드가 전역에서 도는 것과 다름이 없기 때문에 코드를 한줄 작성하는데도 많은 수고와 고민이 필요할 것이다. 또한, 이러한 scope에 대한 이해가 없이 코드를 작성했을 때 예상치 못한 문제가 발생할 수 있다. 그리고 그 문제를 고치는데도 많은 수고가 동반될 것이다.

2). global scope


var a = 10 // global scope

function A() {
  var b = 20
  console.log(a, b)
}

A() // global scope

코드를 처음 작성하기 시작할 때 있는 그곳이 바로 global scope다. 이곳에 많은 정보를 두는 것은 의도치 않은 재할당과 식별자 구분의 어려움 때문에 권장하지 않는다.

 

  • global execution context가 하나밖에 존재하지 못하는 것 처럼, global scope 또한 하나밖에 존재하지 못한다.
  • global scope의 변수는 어디에서든 접근할 수 있다.
  • global scope에 var로 선언한 변수는 global execution context의 creation phase에서 window 객체의 프로퍼티로 삽입된다.

3). local scope


var a = 10

function A() {
  var b = 20 // local scope
  console.log(a, b)
}

A()

함수내에 정의된 식별자들은 local scope에 속한다. 

  • local scope의 변수는 해당 함수의 scope 내에서만 접근이 가능하다. (외부의 다른 함수가 마음대로 접근할 수 없다.)
  • 여러가지 상황에 따라 scope가 변경될 수 있다.
  • 전역 변수와 지역 변수의 식별자가 중복될 경우, 지역 변수 먼저 참조한다. (environment record의 outer를 참조하며 확인 하는 것이기 때문이다.)

3-1). 몇 가지 상황들


이 부분에 나오는 상황들은 poiemaweb.com에서 참고했음을 밝힌다. (아래에 해당 게시물의 링크가 있다.)

 

1. 전역 변수와 지역 변수의 구분

var a = 10 // 전역 변수

function A() {
  var b = 20 // 지역 변수
  console.log(a, b)
}

A()

함수내에서 선언된 변수는 local scope에 존재하므로, scope밖에서는 존재하지 않는다.

 

2. 전역 변수와 지역변수가 중복선언 됐을 때

var x = 'global'

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

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

전역 변수와 선언이 중복되었을 때는, local scope의 변수를 먼저 참조한다.

 

3. 중첩 함수일 때

var x = 'global'

function foo() {
  var x = 'local'
  
  function bar() { // 중첩된 내부 함수
    console.log(x) 
  }
  bar()
}

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

environment record의 outer를 참조하여 scope chain이 일어나므로 아래와 같이 검사하기 때문에 bar의 x는 local이다.

  1. bar 내에서 x라는 식별자가 있나 검색
  2. 없으므로 outer를 타고 올라가 foo에서 x라는 식별자가 있나 검색
  3. 찾았으므로 바로 리턴

 

4. local scope에서 전역 변수의 값을 변경했을 때

var x = 10

function foo() {
  x = 100
  console.log(x)
}
foo() // 100
console.log(x) // 100

함수 혹은 중첩된 함수의 내부에서는 전역 변수의 값을 참조할 수 있기 때문에, 변경 또한 가능하다.

 

5. 중첩 함수에서 상위 함수의 값을 변경했을 때

var x = 10

function foo(){
  var x = 100
  console.log(x) // 100

  function bar(){   // 중첩 함수
    x = 1000
    console.log(x) // 1000
  }

  bar()
}
foo()
console.log(x) // 10

식별자를 가장 가까운 scope에서 찾기 때문에 전역변수 x가 아닌 foo의 지역변수 x의 값이 변경됬다.

4). non block level scope


if (true) {
  var x = 5
}

console.log(x) // 5

block 수준의 scope를 사용하여 x를 선언하였다. 하지만 JS에서는 block 수준의 scope를 사용하지 않는다.

x는 함수 밖에 선언됬으므로 얄짤없이 전역 변수로 취급된다. 따라서 x는 5가 대입된다.

 

하지만, ES6에 추가된 let, const는 var와는 다르게 block 수준의 scope를 지원한다.

if (true) {
  var x = 5
  let y = 10
  const z = 15
}

console.log(x) // 5
console.log(y) // ReferenceError: y is not defined
console.log(z) // ReferenceError: z is not defined

따라서 위와 같이 에러가 난다.

5). lexical scope


var x = 1

function foo() {
  var x = 10
  bar()
}

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

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

JS는 함수를 호출한 곳의 scope에 영향을 받는 것이 아닌, 함수를 선언한 곳의 scope에 영향을 받는다. 따라서 bar의 outer를 참조해서 나오는 곳은 global execution context의 environment record이므로, bar의 x는 1이 나오는 것이다.

 

이 방식을 lexical scope, static scope라고 한다.

 

반대로 함수를 호출한 곳의 scope에 영향을 받아 상위 스코프를 결정하는 방식을 dynamic scope라고 한다. pearl 같은 언어가 dynamic scope를 사용한다.

이 글을 작성할 때 읽은 감사한 자료들.


https://poiemaweb.com/js-scope

 

Scope | PoiemaWeb

스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙으로 자바스크립트는 이 규칙대로 식별자를 찾는다.

poiemaweb.com

https://developer.mozilla.org/en-US/docs/Glossary/Scope

 

Scope

The current context of execution. The context in which values and expressions are "visible" or can be referenced. If a variable or other expression is not "in the current scope," then it is unavailable for use. Scopes can also be layered in a hierarchy, so

developer.mozilla.org

https://scotch.io/tutorials/understanding-scope-in-javascript

 

Understanding Scope in JavaScript

In this tutorial, we will learn everything there is to JavaScript Scope. So, come along.

scotch.io

 

'JS' 카테고리의 다른 글

closure  (0) 2019.12.20
prototype과 prototype chain  (0) 2019.12.16
event loop  (0) 2019.12.11
hoisting  (0) 2019.12.07
execution context의 생성과정  (0) 2019.12.05