[Effective JavaScript] 코드를 캡슐화 하기 위해 문자열보다 클로저를 사용하자

김범식·2023년 7월 7일
0

Effective JavaScript

목록 보기
25/33
post-thumbnail

코드를 캡슐화 하기 위해 문자열보다 클로저를 사용하라


우리는 eval을 사용하여 문자열로 함수를 표현할 수 있다. 그렇다면 코드를 함수로 표현해야 할까 문자열로 표현해야할까? 만약 이런 의심이 들었다면 함수로 표현하는 것이 좋다. 바로 문자열은 클로저가 아니기 때문이다.



문자열 사용

다음과 같은 함수가 있다고 가정해보자

function repeat(n, action){
	for(var i = 0;i<n;i++){
		eval(action);
	}
}

문자열로 입력 받는 action을 eval함수로 실행시키는 구문이다. 모든 변수 참조는 eval에 의해 전역변수로 해석되기 때문에 문제가 없어보일 수 있다.

var start =[], end=[], timing=[]
repeat(1000, "start.push(Date.now()); f(); end.push(Date.now());");
for(var i = 0,n= start.length;i<n;i++){
	timings[i] = end[i] - start[i];
}

이 함수는 불안정 하다 코드를 함수 안으로 이동하면 start, end, timing은 더이상 전역 변수가 아니기 때문이다.

**function benchmark(){**
	var start =[], end=[], timing=[]
	repeat(1000, "start.push(Date.now()); f(); end.push(Date.now());");
	for(var i = 0,n= start.length;i<n;i++){
		timings[i] = end[i] - start[i];
	}
	**return timings**
}

이함수 repeat는 전역변수 start와 end를 참조한다. benchmark는 우연히 start와 end로 바인딩된 어떤 전역변수에 실제로 push하게 되면 프로그램은 예측할 수 없게 된다.



함수 사용

function repeat(n, action){
	for(var i = 0;i<n;i++){
		action();
	}
}

이 방법으로 클로저 내부의 지역변수를 안전하게 참조할 수 있다.

function benchmark(){
	var start = [], end =[], timings=[];
	repeat(1000, function(){ //외부 변수를 참조하는 클로저 함수 생성
		start.push(Date.now());
		f(); //어떤 동작하는 함수
		end.push(Date.now());
	});
	for(var i = 0, n = start.length; i < n;i++){
		timings[i] = end[i]-start[i];
	}
	return timings;

}

function을 익명함수로 생성하므로써 내부에 안전하게 클로저를 형성할수 있다.

eval의 또다른 문제는 일반적으로 고성능 엔진일수록 문자열 내부의 코드를 최적화 하기 어렵다는 점이다. 소스코드를 적절한 시기에 최적화 해야 하는데 문자열 내부의 코드는 그럴 수 없기 때문이다.



기억할 점

  • eval로 실행되는 API에 전달한다면 문자열로 된 지역 변수를 절대 포함시키지 마라.
  • 문자열을 전달받아 eval하는 대신, 함수를 전달받아 호출하는 API를 사용하라
profile
frontend developer

0개의 댓글