자바스크립트 핵심컨샙33 #6. Function Scope, Block Scope and Lexical Scope(함수 스코프, 블록 스코프, 렉시컬 스코프)

김동욱·2021년 7월 4일
0

자바스크립트

목록 보기
6/25
post-custom-banner

Scope

  1. (무엇을 하거나 이룰 수 있는) 기회
  2. (주제조직활동 등이 다루는) 범위
  3. 샅샅이 살피다

스코프란 현재 실행되고있는 컨택스트를 말합니다.
쉽게 말해 현재 실행되고 있는 함수가 가지고 있는 범위를 뜻합니다.
(사실 이게 사이트마다 사람마다 하는 말이 다 달라서 뭐라고 말을 해야할지 참 애매합니다. 그래서 전 이렇게 설명했습니다.😅)

그리고 자바스크립트에서 스코프를 구분하면 크게 2가지로 나룰 수 있습니다.

전역 스코프 (Global scope)
코드 어디에서든지 참조할 수 있다.


지역 스코프 (Local scope or Function-level scope)
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.

var x = 'global';

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

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

foo();//'function'
foo2()//'global'
console.log(x);//'global'

변수 x가 총 2개가 있지만 foo는 자신의 블록 스코프에 있는 'function'을
foo2는 전역 스코프에 있는 'global'을
console.log(x)는 전역 스코프에 있는 'global'을 호출 하였습니다.
전역에 선언된 변수 x는 어디에든 참조할 수 있습니다. 하지만 함수 foo 내에서 선언된 변수 x는 함수 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없습니다.
하지만 foo2에서는 자신의 스코프에 x가 없기때문에 부모 영역으로 나아가서 참조값을 찾았습니다.

즉 변수를 참조하는 '식별자'는 자신이 어디에서 선언됐는지에 의해 자신에게 유효한 범위를
찾습니다. 자바스크립트가 이러한 복잡한 범위를 지정하는 이유는 식별자 이름의 충돌을 막고 구별을 하기 위함입니다.


1. 함수 스코프(function-level scope)

타 언어들은 블록 레벨 스코프(block-level scope)를 따릅니다. 블록 레벨 스코프란 코드 블록({})내에서 유효한 스코프를 의미한다.

하지만 자바스크립트는 함수 레벨 스코프(function-level scope)를 따릅니다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 참조할 수 없다는 뜻입니다. if, for, while등 다른 블록에서 선언된 변수는 자동으로 전역 변수로 참조됩니다.

ECMAScript 6추가된 let, const를 사용하면 블록 레벨 스코프를 사용할 수 있습니다!
ECMAScript는 var의 사용을 자제하고 let, const를 사용하길 권장하고 있습니다.

var x = 1;
var y = 15;

function foo() {
  var y = 10;
  
  function foo2(){
  	  console.log(y);
  }
  
  foo2();
  console.log(x);
}

if(true){
	var z = 3;
}

foo();//10, 1
console.log(z);//3
console.log(y);//error
  • foo()함수 스코프에선 x변수가 없으니 부모 스코프, 즉 글로벌 스코프로 x를 찾았습니다. 그리고 내부함수인 foo2는 y변수를 찾기위해 자신의 스코프를 탐색하다 없으면 가장 인접한 부모 스코프부터 탐색합니다. 바로 위의 스코프가 foo의 스코프이니 y는 글로벌 스코프의 15가 아닌 foo의 10이 출력됩니다.
  • console.log(z)에서 z가 블록 스코프에서 선언되었다고 하지만 자바스크립트는 함수 레벨 스코프 규칙을 준수하기때문에 3이 출력됩니다.
  • 외부에선 foo 블록 내부 스코프에 접근을 할 수 없기때문에 console.log(y)는 error를 반환합니다.

2. 블록 스코프(Block Scope)

위에서 말했듯이 자바스크립트는 함수 레벨 스코프를 따르지만 ECMAScript 6에 추가된 let, const를 사용하면 블록 스코프를 사용할 수 있습니다.

const x = 1;
let y = 15;

function foo() {
  let y = 10;
  
  function foo2(){
  	console.log(y);
  }
  
  foo2();
  console.log(x);
}

if(true){
    let z = 3;
}

foo();//10, 1
console.log(z);//error
console.log(y);//15

위와 똑같은 예제이지만 let과 const는 블록 스코프 규칙을 따르기 때문에 if 블록에 선언된 z는 var과 다르게 전역변수로 선언되지않고 지역변수로만 선언되었습니다.


3. 렉시컬 스코프(Lexical Scope)

lexical

  1. (한 언어의) 어휘의
let name = 'kim';

function func01() {
  console.log(name);
}

function func02() {
  let name = 'lee';
  func01();
}

func02();//name

처음에는 'func02에서 name을 lee로 재할당했으니 console.log(name)은 lee겠군'이라는 생각을 하셨을겁니다. 하지만

😀스코프는 함수를 '호출'할 때가 아니라 '선언'할 때 생깁니다.

이것을 렉시컬 스코핑(lexical scoping)이라고 합니다.

함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳에 있는 변수를 계속 참조하게 됩니다. func01이 선언되었을때 가장 가까운 변수 name의 값은 글로벌 스코프에있는 kim이 됩니다. 그래서 func02에서 lee로 재할당하여도 func01에서 참조하는 값은 변하지 않았습니다.

profile
안녕하세요. 부산에서 근무하고 있는 프론트엔드 개발자 김동욱입니다. 영어 공부 겸 개발 공부를 위해서 글을 작성하고있습니다.
post-custom-banner

0개의 댓글