eval ()과 new Function ()은 같은 것입니까?


92

이 두 기능이이면에서 동일한 작업을 수행합니까? (단일 명령문 함수)

var evaluate = function(string) {
    return eval('(' + string + ')');
}

var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

console.log(evaluate('2 + 1'));
console.log(func('2 + 1'));

3
사실 이것은 jQuery 1.7.2 라인 573에서 사용됩니다. "일부 보안 검사"를 사용하더라도
PicoCreator

2
new이 토론에서 왜 고려됩니까? Function암시 적으로 function object. 제외 new해도 코드는 전혀 변경되지 않습니다. 다음은이를 보여주는 jsfiddle입니다. jsfiddle.net/PcfG8
Travis J

답변:


117

아니요, 동일 하지 않습니다 .

  • eval() 현재 실행 범위 내에서 문자열을 JavaScript 표현식으로 평가하고 로컬 변수에 액세스 할 수 있습니다.
  • new Function()문자열에 저장된 JavaScript 코드를 함수 객체로 구문 분석 한 다음 호출 할 수 있습니다. 코드가 별도의 범위에서 실행되기 때문에 지역 변수에 액세스 할 수 없습니다.

이 코드를 고려하십시오.

function test1() {
    var a = 11;
    eval('(a = 22)');
    alert(a);            // alerts 22
}

사용 된 경우 new Function('return (a = 22);')()지역 변수 a는 해당 값을 유지합니다. 그럼에도 불구하고 Douglas Crockford와 같은 일부 JavaScript 프로그래머 절대적으로 필요한 경우가 아니면 둘 다 사용해서는 안된다고 생각하며 Function신뢰할 수없는 데이터 에서 생성자를 평가 / 사용하는 것은 안전하지 않으며 현명하지 않습니다.


11
"사용해서는 안된다"는 말은 매우 광범위합니다. 어떻습니까, 입력 중 하나가 통제를 벗어 났을 때 절대 사용해서는 안됩니다. 그렇다고해서 JSON 구문 분석을 제외하고는 사용할 필요가 없었습니다. 그러나 여기에서 유효한 사용처럼 보이는 질문에 대답했습니다. 관리자가 최종 사용자가 사용할 수있는 템플릿 기능을 생성하도록 허용하는 것과 같은 작업이 포함되었습니다. 이 경우, 입력은 관리자에 의해 생성되므로 허용되었다
후안 멘데스

3
@Juan : Crockford의 요점은 eval이 자주 오용된다는 것입니다 (귀하의 관점에 따라 다름). 따라서 "모범 사례"JavaScript에서 제외되어야합니다. 그러나 입력이 처음 올바르게 검증 될 때 JSON 또는 산술 표현식 구문 분석과 같은 용도에 유용하다는 데 동의합니다. Crockford조차도 JSON 라이브러리 json2.js에서이를 사용합니다.
PleaseStand 2011 년

그렇다면 이것이 완전히 새로운 실행 컨텍스트 new Function(code)와 동일 eval('(function(){'+code+'})()')하거나 완전히 새로운 것임을 의미 합니까?
George Mauer 2012

5
@GeorgeMauer : eval('(function(){'+code+'})')함수 객체를 반환하는 을 의미한다고 생각 합니다. MDN에 따르면 "Function 생성자로 생성 된 함수는 생성 컨텍스트에 대한 클로저를 생성하지 않습니다. 항상 창 컨텍스트에서 실행됩니다 (함수 본문이"use strict "로 시작하지 않는 한, 컨텍스트가 정의되지 않은 경우)) . "
PleaseStand jul.

6

아니.

업데이트 에서 동일한 결과를 호출 evaluate하고 func생성합니다. 그러나 그들은 "뒤에서 똑같은 일을하는 것"이 ​​가장 확실합니다. 이 func함수는 새 함수를 생성하지만 즉시 실행하는 반면, evaluate함수는 그 자리에서 코드를 실행합니다.

원래 질문에서 :

var evaluate = function(string) {
    return eval(string);
}
var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

이는 매우 다른 결과를 제공합니다.

evaluate('0) + (4');
func('0) + (4');

어쨌든 둘 다 가장 예외적 인 경우를 제외하고 모두 나쁜 습관입니다.
palswim 2011 년

8
당신은 그의 구현에 따라 당신의 모범을 퍼뜨 렸습니다. 그가 평가를 구현했다면 return eval('(' + string + ')');그들은 동일한 결과를 산출 할 것입니다.
Juan Mendes 2011 년

@Juan 나는 생각하지 않았지만 그래. 질문 수정
qwertymk 2011 년

6

new Function재사용 할 수있는 함수를 만듭니다. eval주어진 문자열을 실행하고 마지막 문의 결과를 반환합니다. 평가를 에뮬레이트하기 위해 Function을 사용하는 래퍼 함수를 ​​만들려고 시도했을 때 질문이 잘못되었습니다.

그들이 커튼 뒤에서 몇 가지 코드를 공유한다는 것이 사실입니까? 예, 가능성이 높습니다. 정확히 같은 코드? 아니, 확실히.

재미를 위해 eval을 사용하여 함수를 만드는 내 자신의 불완전한 구현이 있습니다. 그것이 차이에 대해 약간의 빛을 비추 길 바랍니다!

function makeFunction() {
  var params = [];
  for (var i = 0; i < arguments.length -  1; i++) {
    params.push(arguments[i]);
  }
  var code = arguments[arguments.length -  1];


 // Creates the anonymous function to be returned
 // The following line doesn't work in IE
 // return eval('(function (' + params.join(',')+ '){' + code + '})');
 // This does though
 return eval('[function (' + params.join(',')+ '){' + code + '}][0]');
}

이 함수와 새 함수의 가장 큰 차이점은 함수가 어휘 적으로 범위가 지정되지 않는다는 것입니다. 그래서 그것은 클로저 변수에 접근 할 수없고 내 것입니다.


arguments.slice()for 루프 대신 사용 하지 않는 이유 는 무엇입니까? 또는 인수가 참 배열이 아닌 경우 [].slice.call(arguments, 1).
Xeoncross

3

여기 예제에서 사용 된 몇 가지 구문과 그 의미를 지적하고 싶습니다.

 var func = function(string) {
     return (new Function( 'return (' + string + ')' )());
 }

Function (...) () 끝에 "()"가 있습니다. 이 구문은 func가 새 함수를 실행하고 문자열을 반환하는 함수가 아니라 다음을 사용하는 경우 문자열을 반환하도록합니다.

 var func = function(string) {
     return (new Function( 'return (' + string + ')' ));
 }

이제 func는 문자열을 반환하는 함수를 반환합니다.


2

당신이 의미한다면, 그것은 같은 결과를 산출 할 것인가, 그렇다면 그렇다 ... 그러나 단지 평가 (즉, "이 JavaScript 문자열을 평가하라")는 훨씬 더 간단 할 것이다.

아래 편집 :

마치 ...이 두 가지 수학 문제가 동일합니까?

1 + 1

1 + 1 + 1-1 + 1-1 * 1/1


둘 다 문자열을 다시 구문 분석합니까?
qwertymk 2011 년

둘 다 문자열을 구문 분석합니다 (코드 예제에서). "재분석"이 의미하는 바를 모릅니다.
Timothy Khouri 2011 년

1
나는 둘 다 어느 시점에서 문자열을 구문 분석 (평가)한다고 확신하지만 Function객체는 아마도 eval함수를 호출 할 때 개인 멤버 변수에 문자열을 저장합니다 .
palswim 2011 년

1

이 예에서 결과는 동일합니다. 둘 다 전달한 표현식을 실행합니다. 이것이 그들을 매우 위험하게 만드는 것입니다.

그러나 그들은 scense 뒤에 다른 일을합니다. 포함하는 하나는 new Function(), 뒤에 - 더 - 장면, 함수가 호출 될 때 실행되는 사용자가 제공 한 코드에서 익명 함수를 만듭니다.

전달하는 JavaScript는 익명 함수를 호출 할 때까지 기술적으로 실행되지 않습니다. 이는 eval()코드를 즉시 실행하고이를 기반으로 함수를 생성하지 않는 것과는 대조적 입니다.


좀 더 설명해 주 시겠어요? 둘 다 return 문에서 실행되지 않습니까? Function () 하나가 eval 이외의 다른 스택 호출 수준을 사용합니까?
qwertymk 2011 년

Does the Function() one use another stack call level than eval?: eval()입력에서 함수를 생성하지 않고 실행 하기 때문에 그렇게 가정 합니다. new Function()새 함수를 만든 다음 호출합니다.
Chris Laplante 2011 년

@SimpleCoder : Function ()은 호출 스택에 아무것도 추가하지 않습니다. 결과 함수를 호출하는 경우에만. eval은 똑같은 작업을 수행합니다 (질문의 맥락에서 적용되는 경우)
Juan Mendes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.