함수를 만드는 방법이 하나 더 있습니다. 거의 사용되지 않지만 때로는 대안이 없는 경우도 있습니다.
함수를 생성하는 구문은 다음과 같습니다.
let func = new Function ([arg1, arg2, ...argN], functionBody);
함수는 arg1...argN
인수와 주어진 functionBody
사용하여 생성됩니다.
예를 보면 이해하기가 더 쉽습니다. 다음은 두 개의 인수를 갖는 함수입니다:
sum = new Function('a', 'b', 'return a + b'); 경고(합계(1, 2) ); // 3
그리고 여기에 인수는 없고 함수 본문만 있는 함수가 있습니다.
let sayHi = new Function('alert("안녕하세요")'); 안녕하세요(); // 안녕하세요
지금까지 본 다른 방법과의 주요 차이점은 함수가 문자 그대로 런타임에 전달되는 문자열에서 생성된다는 것입니다.
이전의 모든 선언에서는 프로그래머가 스크립트에 함수 코드를 작성해야 했습니다.
그러나 new Function
하면 모든 문자열을 함수로 바꿀 수 있습니다. 예를 들어, 서버로부터 새로운 함수를 받아 실행할 수 있습니다:
let str = ... 서버로부터 코드를 동적으로 수신합니다 ... let func = new Function(str); 기능();
복잡한 웹 애플리케이션에서 서버로부터 코드를 수신하거나 템플릿에서 함수를 동적으로 컴파일하는 등 매우 특정한 경우에 사용됩니다.
일반적으로 함수는 [[Environment]]
특수 속성에서 함수가 어디서 생성되었는지 기억합니다. 이는 생성된 어휘 환경을 참조합니다(이 내용은 변수 범위, 클로저 장에서 다루었습니다).
그러나 함수가 new Function
사용하여 생성되면 해당 [[Environment]]
현재 어휘 환경이 아닌 전역 어휘 환경을 참조하도록 설정됩니다.
따라서 이러한 함수는 외부 변수에 액세스할 수 없고 전역 변수에만 액세스할 수 있습니다.
함수 getFunc() { 값 = "테스트"; let func = new Function('alert(value)'); 반환 기능; } getFunc()(); // 오류: 값이 정의되지 않았습니다.
일반적인 동작과 비교해 보세요.
함수 getFunc() { 값 = "테스트"; let func = function() { 경고(값); }; 반환 기능; } getFunc()(); // getFunc의 어휘 환경에서 "test"
new Function
의 이 특수 기능은 이상해 보이지만 실제로는 매우 유용해 보입니다.
문자열에서 함수를 만들어야 한다고 상상해 보세요. 해당 함수의 코드는 스크립트를 작성할 당시에는 알려지지 않았지만(이것이 우리가 일반 함수를 사용하지 않는 이유입니다), 실행 과정에서 알려지게 됩니다. 우리는 서버나 다른 소스로부터 정보를 받을 수 있습니다.
우리의 새로운 함수는 메인 스크립트와 상호작용해야 합니다.
외부 변수에 접근할 수 있다면 어떨까요?
문제는 JavaScript가 프로덕션에 게시되기 전에 추가 주석, 공백을 제거하여 코드를 축소하는 특수 프로그램인 축소기를 사용하여 압축된다는 것입니다. 중요한 것은 로컬 변수의 이름을 더 짧은 이름으로 바꿉니다.
예를 들어, 함수에 let userName
있는 경우 축소기는 이를 let a
(또는 이 문자가 사용된 경우 다른 문자)로 대체하고 어디에서나 수행합니다. 변수는 로컬이므로 함수 외부의 어떤 것도 이에 액세스할 수 없기 때문에 일반적으로 안전한 작업입니다. 그리고 함수 내에서 축소기는 이에 대한 모든 언급을 대체합니다. 축소기는 똑똑하고 코드 구조를 분석하므로 어떤 것도 손상시키지 않습니다. 그것들은 단지 멍청한 찾기와 바꾸기가 아닙니다.
따라서 new Function
외부 변수에 액세스할 수 있는 경우 이름이 변경된 userName
찾을 수 없습니다.
new Function
외부 변수에 액세스할 수 있다면 축소기에 문제가 있을 수 있습니다.
게다가, 그러한 코드는 구조적으로 좋지 않고 오류가 발생하기 쉽습니다.
new Function
으로 생성된 함수에 무언가를 전달하려면 해당 인수를 사용해야 합니다.
구문:
let func = new Function ([arg1, arg2, ...argN], functionBody);
역사적인 이유로 인수는 쉼표로 구분된 목록으로 제공될 수도 있습니다.
이 세 가지 선언은 동일한 의미를 갖습니다.
new Function('a', 'b', 'return a + b'); // 기본 구문 new Function('a,b', 'return a + b'); // 쉼표로 구분 new Function('a , b', 'return a + b'); // 공백으로 쉼표로 구분됨
new Function
으로 생성된 함수에는 외부 어휘 환경이 아닌 전역 어휘 환경을 참조하는 [[Environment]]
있습니다. 따라서 외부 변수를 사용할 수 없습니다. 하지만 그것은 실제로 좋은 일입니다. 왜냐하면 그것이 우리를 오류로부터 보호해 주기 때문입니다. 매개변수를 명시적으로 전달하는 것은 구조적으로 훨씬 더 나은 방법이며 축소기에 문제를 일으키지 않습니다.