[JavaScript]자바스크립트, 렉시컬 스코프

2021. 7. 28. 15:26Web_Programming/JavaScript

 

 

자바스크립트의 스코프는 아래 두가지 방식으로 동작

  • 렉시컬 스코프 
  • 동적 스코프

💻 렉스타임

 

이전 포스팅에서 살펴 본 것처럼 컴파일러는 토크나이징/렉싱 작업을 수행합니다.

 

이 렉싱 과정에서 생성된 토큰에 의미를 부여하는데 이 개념이 렉시컬 스코프의 바탕이 됩니다.

 

👉 렉시컬 스코프 : 렉싱 타입에 정의되는 스코프

 

+ 개발자가 코드 짤 때, 변수와 스코프 블록을 어디서 작성하는가에 기초하여 렉서가 코드 처리

 

예제

function foo(a){
	var b= a*2;
    function bar(c){
    	console.log(a, b, c);
    }
    bar(b*3);
}

foo(2); //2, 4, 12

3개의 중첩 스코프(스코프 버블)

  • 글로벌 스코프, 확인자 - foo
  • foo 스코프, 확인자 - a, var, b
  • bar 스코프, 확인자 - c

❗ 어떤 함수의 버블도 동시에 다른 두 스코프 버블 안에 존재 할 수 없음.

 

 

💡 검색

 

엔진의 확인자 검색을 위한 정보

  • 스코프 버블의 구조
  • 상대적 위치
function foo(a){
	var b= a*2;
    function bar(c){
    	console.log(a, b, c);
    }
    bar(b*3);
}

foo(2); //2, 4, 12

 

console(a, b, c) 실행 👉 a, b, c검색 절차

  1. bar 스코프에서 시작, a검색 실패 -> foo 스코프에서 검색, a 사용 (b 동일)
  2. c는 bar 스코프 내에서 검색 가능

❗ 스코프는 목표의 대상을 찾는 즉시 검색 중단. 실행시점 가장 안쪽 스코프에서 시작

 

❗ 렉시컬 스코프는 함수가 선언된 위치에 따라 정의

 

+ 렉시컬 스코프는 a,b,c와 같은 일차 확인자 검색에만 적용,

foo.bar.baz의 참조는 foo확인자 검색에서만 렉시컬 스코프사용, 이후는 객체 속성접근 규칙을 통해 가져옴.


💻 렉시컬 속이기

 

권장하지 않는 방법이지만, 런타임 때 렉시컬 스코프를 수정할 수 있는 방법이 있습니다.

 

💡 eval()

 

eval()함수는 인자로 문자열을 받아 런타임에 문자열 내용을 코드처럼 처리

 

eval()이 호출된 위치에 있는 렉시컬 스코프를 수정

 

+이외에도, setTimeout() / setInterval()/ new Function() 하지만, 성능 저하로 사용하지 않는 것이 좋음

 

💡 with

한 객체의 여러 속성을 참조할때 매번 객체 참조를 하지 않기위한 기법

function foo(obj) {
  with (obj) {
    a = 2;
  }
}
var o1 = {
  a: 3
};
var o2 = {
  b: 3
};
foo(o1);
console.log(o1.a); //2
foo(o2);
console.log(o2.a); //undefined
console.log(a); //2-Oops, leaked global!

foo(o2)에서 o2는 a속성값이 없어 o2.a는 undefined,

👉 with문에서 a=2;가 수행되면, 글로벌 스코프에서도 a를 찾을 수 없어 자동으로 글로벌 변수 생성

 

eval()이미 존재하는 렉시컬 스코프를 수정,

with문은 넘겨진 객체를 가지고 하나의 새로운 렉시컬 스코프를 생성

 

자바스크립트 엔진은 렉싱된 코드를 분석하여 위치를 파악하여 실행 과정에서 확인자 검색을 더빠르게함

하지만, eval()이나 with문으로 확인자의 위치를 파악할 수 없어져 최적화의 의미가 사라져 코드가 느려짐.

반응형