Javascript - 스코프 관리

김병민·2022년 6월 28일
0

TIL

목록 보기
64/68
post-thumbnail

을 읽고 작성하였습니다.

스코프 관리

스코프

스코프란 참조 대상 식별자를 찾아내기 위한 규칙입니다.
참조 대상 식별자란 말이 쉽게 말해 변수라고 생각하면 됩니다.

const here = "kitchen"

function whereIsMyCheese (){
	console.log(here)
}
whereIsMyCheese()

자 여기서 함수 whereIsMyCheese 안에는 here이라는 변수가 존재하지 않습니다. 그치만 위 코드를 실행한다면 콘솔에는 kitchen이라는 값이 출력될 것입니다. 여기서 herewhereIsMyCheese참조 대상 식별자입니다.

함수 whereIsMyCheese는 here이라는 값을 찾기 위해 지역 스코프를 확인할 것입니다. 그리고 지역 스코프에 이것이 없으면 상위 지역 즉 whereIsMyCheese전역 스코프를 확인하여 here을 찾아낼 것입니다.


이렇게 값을 찾아가는 일련의 과정을 스코프 체이닝이라하며 이러한 관계는 스코프 체인이라고 합니다.

스코프 관리

그럼 이러한 스코프를 어떻게 관리해야 자바스크립트의 성능를 최적화할 수 있을까요 ?

적절한 위치에 값 선언하기

사실 가장 좋은 방법은 적절한 위치에 변수를 선언하는 것입니다.

function rusianDoll (){
const here = "Doll!"
  
	function rusianDollOne(){
    	function rusianDollTwo(){
        	function rusianDollThree(){
            	console.log(here)
            }
        }
    }
}
rusianDoll()

극단적인 이 코드를 한번 봐봅시다.
이 코드에서 here은 맨 처음 rusianDoll 안에서 선언되었지만 사용은 rusianDollThree에서 이루어졌습니다.

해당 함수는 here의 값을 찾기 위해 rusianDollThree => rusianDollTwo => rusianDollOne까지 확인을 한 뒤에야 here값을 가지고 올 것입니다. 이러한 과정이 쌓이고 쌓이다보면 성능 저하로 이루어지겠죠.

function rusianDoll (){
  
	function rusianDollOne(){
    	function rusianDollTwo(){
        	function rusianDollThree(){
				const here = "Doll!"
            	console.log(here)
            }
        }
    }
}
rusianDoll()

위와 같이 here을 적절한 위치로 수정하여 체이닝 과정을 줄입시다.

중복값 처리

function iniUI(){
	let bd = document.body,
        links = document.getElementByTagName("a"),
        i = 0,
        len = links.length;
  while(i<len){
  	update(links[i++])
  }
  
  document.getElementById("go-btn").onClick = function(){
    doSomeThing()
                                                        
    };
  bd.className= "active"
}

사실 이 유형은 제가 가장 많이 하는 실수 중 하나입니다.

여러분들은 이 코드를 보며 문제점을 파악하셨나요 ??

정답은 바로 document의 중복 사용입니다.

document를 찾는 과정을 설명하면 빠를 것입니다. iniUI함수를 실행하면 document를 찾기위해 iniUI의 상위 지역 스코프를 확인할 것입니다. 그렇게 확인을 반복하다가 마지막 전역스코프를 확인하고 거기서 document를 가져올 것입니다.

그 과정을 bd,links,onClick할당 총 세번 이루어집니다. 이것은 간단한 로직이라 그렇지만 엄청 복잡하고 긴 함수라면 더 많은 스코프체이닝이 이루어질 것입니다.

이러한 문제점을 피하기 위해 우리는 document를 찾는 과정을 한번만 하게 해줘야 합니다.

function iniUI(){
	let doc = document,
        bd = doc.body,
        links = doc.getElementByTagName("a"),
        i = 0,
        len = links.length;
  while(i<len){
  	update(links[i++])
  }
  
  doc.getElementById("go-btn").onClick = function(){
    doSomeThing()
                                                        
    };
  bd.className= "active"
}

그렇게 코드를 변경한다면 단 한번의 스코프체이닝만 이루어질 것입니다.

try..catch를 활용한 스코프 체인 확장

try..catch를 활용하면 스코프 체인을 확장한다면 성능 하락을 최소화할 수 있습니다.

try{
	error()
}catch(ex){
	handleError(ex) //에러처리 함수에 에러처리를 위임합니다.
}

여기서 handleError는 에러가 났을 때 생성되는 예외 객체를 넘겨받아 적절한 방법으로 처리합니다. catch절에는 실행문 하나만 있고 지역 변수가 없으므로 임시 스코프 체인 확장이 성능에 영향을 주지 않습니다.

또한 catch문은 스코프에 영향을 주지 않습니다.

let sports = "a";
try {
  let sports = "basketball";
  abc = error;
  console.log("try : ", sports);
} catch (e) { 
    sports = "football";
  console.log("catch : ", sports);
}

console.log("밖 : ", sports);

위 코드를 실행하면 console.log("catch : ", sports);console.log("밖 : ", sports);의 결과가 football이라는 것을 알 수 있습니다. 이는 스코프에 영향을 받지 않는다는 것 또한 알 수 있습니다.

하지만 catch를 마구 사용하면 안됩니다. try-catch문을 에러가 있을지도 모를 때 쓰는 것이지 에러 처리를 위한 것이 아닙니다. 에러가 자주 발생할 것이라고 생각한다면 코드를 수정하는 것이 맞습니다.

profile
I'm beginner

0개의 댓글