[JavaScript] 호이스팅 / 스코프, 스코프 체인

Hyein Son·2020년 10월 16일
1

JavaScript

목록 보기
9/10

VariableEnvironment / LexicalEnvironment

  • environmentRecord와 outer-EnvironmentReference로 구성

호이스팅

  • environmentRecord : 현재 컨텍스트와 관련된 코드의 식별자 정보(매개변수 이름, 함수 선언, 변수명)가 저장된다. 컨텍스트 내부 전체를 훑어나가며 순서대로 수집한다. 이 과정을 추상화한 개념이 호이스팅이다.
  • var선언부, 함수 선언부를 최상단으로 올린 후 동작하는 것을 말하는 가상의 개념이다. 실제로 일어나는 것이 아니다.
function a () {
  console.log(b);
  var b='bbb';
  console.log(b);
  function b (){
  
  };
  console.log(b);
}
a();

위의 실행결과는 var bfunction b(){}가 호이스팅 돼 다음과 같다.

[Function: b]
'bbb'
'bbb'

함수 선언문과 함수 표현식

함수 선언문 : function 정의부만 존재하고 별도의 할당 명령이 없는 것

  • 함수명이 반드시 필요
function a(){   }
a();

함수 표현식 : 정의한 function을 별도의 변수에 할당하는 것

  • 함수명이 있는 경우, 기명 함수 표현식 / 없는 경우, 익명 함수 표현식 이라고 한다. 일반적으로 함수 표현식은 익명 함수 표현식을 의미한다.
// 익명 함수 표현식
var b = function(){   }
b();

// 기명 함수 표현식
var c = function d(){    }
c();
d(); // 에러

기명 함수 표현식의 경우, 함수명으로 외부에서 호출할 수 없다. 함수명은 함수 내부에서만 접근할 수 있다. 따라서 함수명을 재귀함수 호출 시 사용한다.

❗️함수 선언문의 위험성

console.log(sum(3, 4));
function sum (x, y) {
  return x + y;
}

var a = sum(1,2);
console.log(a);

function sum (x, y) {
  return '결과:'+ (x + y)
}

var c = sum(1,2);
console.log(c);
결과:7
결과:3
결과:3

함수 선언문을 사용하는 경우, 함수 전체가 호이스팅이 일어나기 때문에 중복 선언 했을 경우 그 이전에 선언된 함수가 무시된다. 중복 선언하기 전의 코드부터 중복 선언한 함수식을 사용하게 되는 문제가 발생한다.
따라서 전역공간에 함수를 선언하거나 동명의 함수를 중복 선언하는 일은 지양해야한다. 되도록이면 함수 표현식을 사용하도록 한다.


스코프, 스코프 체인

스코프(scope) : 식별자에 대한 유효범위

  • es5에서는 함수 스코프(var)만 존재했다. es6에서 블록 스코프가 도입되었는데 let, const, class, strict mode에서의 함수 선언만 해당한다.

스코프 체인(scope chain)

  • 식별자에 대한 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것
  • outerEnvironmentReference에 의해 이루어진다.
    outerEnvironmentReference는 참조하는 외부 정보를 뜻하는데 현재 호출된 함수가 선언된 위치의(바로 직전 컨텍스트의) LexicalEnvironment 정보를 참조한다.
var A = function(){
    var B = function(){
    	var C = function(){
        
        };
        C();
    };
    B();
}
A();

함수 C의 outerEnvironmentReference --> B의 LexicalEnvironment
함수 B의 LexicalEnvironment에 있는 outerEnvironmentReference --> A의 LexicalEnvironment
함수 A의 LexicalEnvironment에 있는 outerEnvironmentReference --> 전역 컨텍스트의 LexicalEnvironment

이처럼 각 outerEnvironmentReference는 선언 시점의 LexicalEnvironment를 참조하기 때문에 가장 가까운 요소부터 차례대로 접근이 가능하다. 따라서 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근이 가능하다. 같은 이름으로 외부에서 선언되었더라도 가까운 위치에 이미 선언이 되어있다면 외부에서 선언된 변수에는 접근할 수 없다.

0개의 댓글