📢 함수를 만들 수 있는 방법 중 하나
문법
◾️ 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 문법]
📌 [MDN Function 생성자]
'모던 자바스크립트' 카테고리의 다른 글
6.9 call/apply와 데코레이터, 포워딩 (0) | 2020.08.31 |
---|---|
6.8 setTimeout과 setInterval을 이용한 호출 스케줄링 (0) | 2020.08.26 |
6.6 객체로서의 함수와 기명 함수 표현식 (0) | 2020.08.24 |
6.5 전역 객체 (0) | 2020.08.22 |
6.4 오래된 'var' (0) | 2020.08.21 |