본문 바로가기

모던 자바스크립트

6.7 new Function 문법

📢 함수를 만들 수 있는 방법 중 하나 

 

문법

◾️ new Function 문법을 사용하면 함수를 만들 수 있다. 

let func = new Function ([arg1, arg2, ...argN], functionBody);

◾️ 두개의 인수를 가진 함수

let sum = new Function('a', 'b', 'return a + b');

console.log( sum(1, 2) ); // 3

◾️ 인수가 없고 함수 본문만 있는 함수

let sayHi = new Function('console.log("Hello")');

sayHi(); // Hello

◾️ new Function을 사용해 함수를 만드는 방법의 가장 큰 차이는 런타임에 받은 문자열을 사용해 함수를 만들 수 있다.

◾️ 함수 표현식과 함수 선언문은 직접 스크립트를 작성해야 함수를 만들 수 있지만 new Function을 사용하면 어떤 문자열도 함수로 바꿀 수있다. 

◾️ 서버에서 전달 받은 문자열을 이용해 새로운 함수를 만들고 이를 실행하는 것도 가능하다. 

let str = ... 서버에서 동적으로 전달받은 문자열(코드 형태) ...

let func = new Function(str);
func();

◾️ 서버에서 코드를 받거나 템플릿을 사용해 함수를 동적으로 컴파일해야 하는 경우, 복잡한 웹 애플리케이션을 구현할 때와 같이 아주 특별한 경우에 new Function을 사용할 수 있다. 

 

클로저

◾️ 함수는 특별한 프로퍼티 [[Environment]]에 저장된 정보를 이용해 자기 자신이 태어난 곳을 기억한다. 

◾️ [[Environment]]는 함수가 만들어진 렉시컬 환경을 참조한다. 

◾️ new Function을 이용해 함수를 만들면 함수의 [[Environment]] 프로퍼티가 현재 렉시컬 환경이 아닌 전역 렉시컬 환경을 참조

◾️ new Function을 이용해 만든 함수는 외부 변수에 접근할 수 없고, 오직 전역 변수에만 접근할 수 있다. 

function getFunc() {
  let value = 'test';
  
  let func = new Function('console.log(value)');
  
  return func;
}

getFunc()(); // ReferenceError: value is not defined

◾️ 일반적인 방법을 사용해 함수를 정의했을 때

function getFunc() {
  let value = 'test';
  
  let func = function () {console.log(value)};
  
  return func;
}

getFunc()(); // getFunc의 렉시컬 환경에 있는 값 test가 출력된다

◾️ new Function으로 만든 새로운 함수 내부에서 외부 변수에 접근하려 할 때, 기존 함수 선언 방식으로 작성한 함수와 동일한 동작이 보장되어야 한다. 

◾️ 그런데 스크립트 프로덕션 서버에 반영되기 전, 압축기(minifier)에 의해 압축될 때 문제가 발생한다. 압축기는 스크립트에서 주석이나 여분의 공백 등을 업애 코드 크기를 줄여주는 특수한 프로그램인데 압축기가 지역 변수 이름을 짧게 바꾸면서 문제가 발생한다.

◾️ 함수 내부에 let userName라는 변수가 있으면 이 지역변수는 압축기에 의해 let a등(짧은 이름)으로 대체되는데, 이때 userName 모두가 a 로 교체된다. 

◾️ userName은 지역변수이고, 함수 외부에선 함수 내부에 있는 변수에 접근할 수 없기 때문에 이렇게 해도 전혀 문제가 없다.

◾️ 압축기는 단순히 변수를 찾아서 바꾸지 않고 코드 구조를 분석해 기존에 작성한 코드의 기능을 망가뜨리지 않으면서 제 역할을 수행.

◾️ 이런 동작 방식 때문에 new Function 문법으로 만든 함수 내부에서 외부 변수에 접근하려고 하면 userName은 이미 이름이 변경되었기 때문에 찾을 수 없게 된다. 

◾️ 압축기가 동작한 이후엔, new Function으로 만든 함수 내부에서 외부 렉시컬 환경에 접근하려고 할 때 문제가 발생할 수있다. 

◾️ new Function으로 만든 함수에 무언갈 넘겨주고 싶다면 인수를 사용하자

 

 

 

📝 요약

◽️ new Function을 이용해 만든 함수의 [[Environment]]는 외부 렉시컬 환경이 아닌 전역 렉시컬 환경을 참조하므로 외부 변수를 사용할 수 없다. 단점 같아 보이는 특징이긴 하지만 에러를 예방해 준다는 관점에선 장점이 되기도 한다. 구조상으론 매개변수를 사용해 값을 받는 게 더 낫다. 압축기에 의한 에러도 방지할 수 있다. 

 



📝 오늘 새롭게 배운 내용 📝

 

✅ 함수를 정의하는 새로운 방법 !!

✅ 런타임에 받은 문자열을 사용해 함수를 만들 수 있다!!! 

✅ new Function으로 정의한 함수는 외부 변수에 접근할 수 없고 오직 전역 변수에만 접근할 수 있다. 

함수의 [[Environment]] 프로퍼티가 현재 렉시컬 환경이 아닌 전역 렉시컬 환경을 참조하기 때문

✅ 실제로 쓰여진 걸 본적이 없어서 감은 안잡히지만 동적으로 함수를 정의할 때 사용하면 좋은 방법인거 같다.

✅ 함수 내부에서 외부 변수에 접근하는 것은 그렇게 좋은 방법은 아니다... 

 

 

 

📌 [JAVASCRIPT_INFO new Function 문법]

 

'new Function' 문법

 

ko.javascript.info

📌 [MDN Function 생성자]

 

Function

Function 생성자는 새 Function 객체를 만듭니다.

developer.mozilla.org