JavaScript eval 함수를 사용하는 것이 나쁜 생각 인 이유는 무엇입니까?


534

eval 함수는 코드를 동적으로 생성하는 강력하고 쉬운 방법이므로주의해야 할 점은 무엇입니까?


92
사이먼 윌리 슨에 의해 평가 ()하지 마십시오 - 24ways.org/2005/dont-be-eval
브라이언 싱

5
에 설명 된대로 moduscreate.com/javascript-performance-tips-tricks - (새로운 기능 (STR))는 () 평가 (STR)보다 더 성능이 좋은 것입니다. 그냥 내 2 센트 :)
Grgur

3
분명히 (a)는 67 % 느린 크롬에 대한 평가 (A)보다 더 새로운 fcuntion입니다
잠 것입니다

나를 위해 새로운 기능은 (a) osx에서 최신 크롬이 80 % 느리다
john Smith

3
성능을 비교하기 위해 정적 함수를 추가했습니다. jsperf.com/eval-vs-new-function/2
Nepoxx

답변:


386
  1. eval을 부적절하게 사용하면 주입 공격에 대한 코드가 열립니다.

  2. 디버깅 은 더 어려울 수 있습니다 (행 번호 등 없음)

  3. eval'd 코드가 느리게 실행 됨 (eval'd 코드를 컴파일 / 캐시 할 기회 없음)

편집 : @ Jeff Walden이 의견에서 지적했듯이 # 3은 2008 년보다 오늘날에는 덜 사실입니다. 그러나 컴파일 된 스크립트의 일부 캐싱이 발생할 수 있지만 수정없이 반복되는 스크립트로만 제한됩니다. 더 가능성이 높은 시나리오는 매번 약간 씩 수정 된 스크립트를 평가하여 캐시 할 수 없다는 것입니다. 일부 평가 된 코드가 더 느리게 실행된다고 가정 해 봅시다.


2
@JeffWalden, 좋은 의견. 게시 한 지 1 년이 지났지 만 게시물을 업데이트했습니다. Xnzo72, 만약 당신이 (Jeff처럼) 당신의 의견을 어느 정도 검증했다면, 나는 당신과 동의 할 수있을 것입니다. Jeff는 "동일한 문자열을 여러 번 평가하면 구문 분석 오버 헤드를 피할 수 있습니다"라고 키를 지적했습니다. 그대로, 당신은 단지 잘못입니다. # 3은 많은 시나리오에 적용됩니다.
Prestaul

7
@Prestaul : 가정 된 공격자가 클라이언트에서 JavaScript를 변경하기 위해 개발자 도구를 사용할 수 있기 때문에 왜 Eval ()이 코드를 주입 ​​공격에 노출 시키는가? 아직 열지 않았습니까? (물론 클라이언트 JavaScript에 대해 이야기하고 있습니다)
Eduardo Molteni

60
@EduardoMolteni, 우리는 사용자가 자신의 브라우저에서 js를 실행하는 것을 신경 쓰지 않으며 실제로 막을 수 없습니다. 우리가 피하려고하는 공격은 사용자가 제공 한 값이 저장되고 나중에 자바 스크립트에 저장되어 평가 될 때입니다. 예를 들어 사용자 이름을 다음 badHackerGuy'); doMaliciousThings();과 같이 설정할 수 있습니다. 사용자 이름을 가져 와서 다른 스크립트로 연결하여 다른 사람들의 브라우저에서 평가하면 컴퓨터에서 원하는 모든 자바 스크립트를 실행할 수 있습니다 (예 : 내 게시물을 +1하도록 강제, 내 서버 등에 데이터를 게시하십시오.)
Prestaul

3
일반적으로 # 1은 대부분의 함수 호출은 아니지만 많은 경우에 해당됩니다. 경험이없는 프로그래머가 eval ()을 배제하고 피해서는 안됩니다. 경험이없는 프로그래머가이를 악용하기 때문입니다. 그러나 숙련 된 프로그래머는 종종 코드에서 더 나은 아키텍처를 가지게되며,이 더 나은 아키텍처로 인해 eval ()이 거의 필요하지 않을 수도 있습니다.
frodeborli

4
@TamilVendhan 물론 중단 점을 넣을 수 있습니다. debugger;명령문을 소스 코드 에 추가하여 코드화를 위해 Chrome에서 생성 한 가상 파일에 액세스 할 수 있습니다 . 해당 라인에서 프로그램 실행이 중지됩니다. 그런 다음 다른 JS 파일과 같은 디버그 중단 점을 추가 할 수 있습니다.
Sid

346

평가가 항상 악한 것은 아닙니다. 완벽하게 적절한 때가 있습니다.

그러나 평가는 현재 그리고 역사적으로 자신이하는 일을 모르는 사람들에 의해 과도하게 사용되고 있습니다. 불행히도 JavaScript 자습서를 작성하는 사람들이 포함되며 경우에 따라 보안에 영향을 줄 수 있습니다. 따라서 eval에 물음표를 던질수록할수록 좋습니다. eval을 사용할 때마다 수행중인 작업의 위생 상태를 점검해야합니다. 더 안전하고 깔끔한 방법으로 수행 할 수 있기 때문입니다.

변수를 'potato'에 저장 한 id로 요소의 색상을 설정하려면 일반적인 예를 들자면 :

eval('document.' + potato + '.style.color = "red"');

위와 같은 코드의 작성자가 JavaScript 객체의 작동 원리에 대한 단서가 있었다면 리터럴 점 이름 대신 대괄호를 사용할 수 있다는 사실을 깨달았을 것입니다.

document[potato].style.color = 'red';

... 읽기가 훨씬 쉬우 며 버그가 적습니다.

(그러나, 자신이하고있는 일을 / 정말로 / 알고있는 사람은 :

document.getElementById(potato).style.color = 'red';

문서 객체에서 DOM 요소에 직접 액세스하는 오래된 트릭보다 더 안정적입니다.)


82
흠, 처음 JavaScript를 배울 때 운이 좋았다고 생각합니다. 저는 항상 "document.getElementById"를 사용하여 DOM에 액세스했습니다. 아이러니하게도, 나는 자바 스크립트에서 객체가 어떻게 동작했는지에 대한 단서가 없었기 때문에 그 당시에 만 해냈다.
Mike Spross

5
동의하다. 때때로 평가 웹 서비스에서 JSON 응답에 대한 확인을 예입니다
schoetbi

40
@ schoetbi : JSON JSON.parse()대신 사용하지 않아야 eval()합니까?
nyuszika7 시간

4
@bobince code.google.com/p/json-sans-eval 은 모든 브라우저에서 작동하므로 github.com/douglascrockford/JSON-js도 마찬가지 입니다. Doug Crockford의 json2.js는 내부적으로 eval을 사용하지만 확인을 사용합니다. 또한 JSON에 대한 기본 제공 브라우저 지원과 호환됩니다.
Martijn

8
@bobince 누락 된 JSON 라이브러리 및 기타 사항을 처리하기위한 기능 감지 및 폴리 필이라는 것이 있습니다 ( modernizr.com 참조 )
MauganRa

37

문자열에서 JavaScript 함수를 실행할 수 있기 때문이라고 생각합니다. 이를 사용하면 사람들이 악성 코드를 응용 프로그램에 쉽게 삽입 할 수 있습니다.


5
그렇다면 대안은 무엇입니까?
현대

5
실제로 대안은 필요하지 않은 코드를 작성하는 것입니다. Crockford는 이것에 대해 자세히 설명하고, 그것을 사용해야한다면 프로그램 디자인 결함과 재 작업이 필요하다고 말합니다. 사실, 나는 그도 동의합니다. 모든 결함에 대한 JS는 실제로 유연하며 유연하게 사용할 수있는 공간이 많이 있습니다.
kemiller2002

3
사실은 아니지만 대부분의 프레임 워크에는 JSON 구문 분석 방법이 있으며 프레임 워크를 사용하지 않는 경우 JSON.parse ()를 사용할 수 있습니다. 대부분의 브라우저는이를 지원하며, 실제로 꼬집어 있으면 JSON에 대한 파서를 매우 쉽게 작성할 수 있습니다.
kemiller2002

6
이 인수는 구입하지 않습니다. 이미 악성 코드를 Javascript 응용 프로그램에 삽입하기 쉽습니다. 브라우저 콘솔, 스크립트 확장 등이 있습니다. 클라이언트에 전송되는 모든 단일 코드는 클라이언트가 실행할 수있는 옵션입니다.
user2867288

6
요점은 브라우저에 코드를 삽입하는 것이 더 쉽다는 것입니다. 쿼리 문자열에 eval을 사용한다고 가정 해 봅시다. 쿼리 문자열이 첨부 된 해당 사이트로 연결되는 링크를 클릭하도록 속이는 경우 이제 브라우저의 모든 권한을 사용하여 컴퓨터에서 코드를 실행했습니다. 해당 사이트에 입력 한 모든 내용을 키 기록하여 보내 주시겠습니까? eval이 실행될 때 브라우저가 가장 높은 권한을 부여하기 때문에 나를 막을 방법이 없습니다.
kemiller2002

27

두 가지 점이 생각납니다.

  1. 보안 (하지만 직접 평가할 문자열을 생성하는 한, 이것은 문제가되지 않을 수 있음)

  2. 성능 : 실행될 코드를 알 수 없을 때까지 최적화 할 수 없습니다. (자바 스크립트 및 성능, 확실히 Steve Yegge의 프레젠테이션 )


9
클라이언트가 우리 코드로 원하는 것을 할 수 있다면 왜 보안이 문제가됩니까? 그리스 몽키?
Paul Brewczynski

2
사용자 A가 코드를 자신의 일부가 될 저장할 때 @PaulBrewczynski는 보안 문제가 나타납니다 eval, 다음 uated 해당 사용자의 B 브라우저에서 코드 실행의 작은 조각
펠리페 페레이라

21

사용자 입력을 eval ()에 전달하는 것은 보안 위험이지만 eval ()을 호출 할 때마다 JavaScript 인터프리터의 새 인스턴스가 작성됩니다. 이것은 자원 돼지 일 수 있습니다.


27
내가 대답 한 이후 3 년 이상 동안, 무슨 일이 일어나는지에 대한 이해가 깊어졌습니다. 실제로 발생하는 것은 새로운 실행 컨텍스트가 생성 된 것입니다. dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Andrew Hedges

20

일반적으로 평가판 사용자 입력을 전달하는 경우에만 문제가됩니다.


16

주로 유지 관리 및 디버그가 훨씬 어렵습니다. 그것은 같다 goto. 사용할 수는 있지만 나중에 변경해야 할 사람들에게 문제를 찾기 어렵고 어렵게 만듭니다.


Eval은 템플릿과 같은 누락 된 메타 프로그래밍 기능을 대체하는 데 사용할 수 있습니다. 나는 기능에 대한 끝없는 기능 목록보다 소형 발전기 방식을 좋아합니다.
weaknespase 2016

문자열이 사용자가 제공하지 않거나 가능한 브라우저로 제한되는 한. JavaScript는 프로토 타입 변경, obj [member], Proxy, json.parse, 창, 데코레이터 함수 (부사), newf = decorator (oldf), Array.prototype.map (f)와 같은 고차 함수와 같은 것을 사용하여 메타 프로그래밍 능력이 많이 있습니다. {}을 통해 키워드 인수를 다른 함수에 인수를 전달합니다. eval 대신 이러한 작업을 수행 할 수없는 사용 사례를 말씀해 주시겠습니까?
aoeu256

13

명심해야 할 것은 eval ()을 사용하여 제한된 환경에서 코드를 실행할 수 있다는 것입니다. 특정 JavaScript 함수를 차단하는 소셜 네트워킹 사이트는 eval 블록으로 분리하여 속일 수 있습니다.

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

따라서 허용되지 않을 수있는 JavaScript 코드를 실행하려는 경우 ( Myspace , 당신을보고 있습니다 ...) eval ()은 유용한 트릭입니다.

그러나 위에서 언급 한 모든 이유로 인해 완전한 제어 권한이있는 자체 코드에는이 코드를 사용해서는 안됩니다. 필요하지 않으며 'tricky JavaScript hacks'선반으로 강등됩니다.


1
위 코드를 업데이트하기 만하면됩니다. --hi there!-는 문자열이므로 따옴표로 묶어야합니다. eval ( 'al'+ 'er'+ 't ('+ ' "hi there!"'+ ')');
Mahesh

2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Konrad Borowski

3
Yikes, alert ()를 제한하지만 eval ()을 허용하는 소셜 네트워킹 사이트가 있습니까?
joshden

12

eval ()에 cgi 또는 input을 통한 동적 내용을 허용하지 않으면 페이지의 다른 모든 JavaScript와 마찬가지로 안전하고 견고합니다.


이것이 사실이지만 콘텐츠 동적 인 것이 아니라면 eval을 사용하는 이유는 무엇입니까? 코드를 함수에 넣고 대신 호출 할 수 있습니다!
Periata Breatta

예를 들어 Ajax 호출에서 온 반환 값 (JSON과 같은 서버 정의 문자열 등)을 구문 분석합니다.
Thevs

2
아, 알겠습니다 나는 고객이 무엇인지 미리 알지 못하기 때문에 역동적이라고 부를 것이지만 지금은 당신이 무엇을 의미하는지 알 수 있습니다.
Periata Breatta

7

나머지 답변과 함께 평가 진술이 고급 최소화 될 수 있다고 생각하지 않습니다.


6

보안 위험 가능성이 있으며 실행 범위가 다르며 코드 실행을위한 완전히 새로운 스크립팅 환경을 생성하므로 매우 비효율적입니다. 자세한 내용은 여기를 참조하십시오 : eval .

그러나 매우 유용하며 중재와 함께 사용하면 많은 기능을 추가 할 수 있습니다.


5

평가되는 코드가 신뢰할 수있는 소스 (일반적으로 자신의 응용 프로그램)에서 온 것임을 100 % 확신하지 않는 한 시스템을 사이트 간 스크립팅 공격에 노출시키는 확실한 방법입니다.


1
서버 측 보안이 좋지 않은 경우에만. 클라이언트 측 보안은 말도 안됩니다.
doubleOrt

5

나는이 토론이 오래 되었다는 것을 알고 있지만 Google 의이 접근법을 정말로 좋아 하며 다른 사람들과 그 느낌을 나누고 싶었습니다.)

다른 것은 더 나은 당신이 얻을 것이다 더 많이 이해하려고 노력 그리고 마지막으로 당신은 그냥 뭔가 누군가가 그렇게 :)이 매우 영감했다해서 좋거나 나쁜 생각하지 않는다 비디오 나 자신에 의해 더 생각하는 데 도움이 :) 좋은 연습은 좋지만 마음대로 사용하지 마십시오. :)


1
예. 적어도 지금까지 Chrome에서보다 효율적인 사용 사례를 발견했습니다. 반복 할 때마다 주어진 변수에서 문자열을 제거하는 RAF를 실행하십시오. setInterval을 사용하여 해당 문자열에서 변환 설정 등과 같은 그래픽 지향 항목 만 설정하십시오. 배열의 함수를 반복하거나 변수를 사용하여 변경된 요소의 변환 만 설정하는 것과 같은 다른 많은 접근법을 시도했지만 지금까지 가장 효율적인 것으로 보입니다. 그것이 애니메이션에 관한 한, 가장 진정한 벤치 테스트는 당신의 눈입니다.
jdmayfield

5

사용중인 컨텍스트를 알고 있다면 반드시 나쁘지는 않습니다.

애플리케이션이 XMLHttpRequesteval() 에서 돌아온 일부 JSON에서 오브젝트를 작성하는 데 사용중인 경우 에서 신뢰할 수있는 서버 측 코드로 생성 된 자신의 사이트로 경우 문제가되지 않습니다.

신뢰할 수없는 클라이언트 측 JavaScript 코드는 어쨌든 그렇게 할 수 없습니다. 실행중인 eval()것이 합리적인 소스에서 온 것이라면 괜찮습니다.


3
JSON을 파싱하는 것보다 eval을 사용하지 않습니까?
Brendan Long

@Qix-내 브라우저 (Chrome 53)에서 해당 테스트를 실행하면 평가 보다 구문 분석이 다소 빠릅니다 .
Periata Breatta

@PeriataBreatta 허, 이상하다. 왜 그런지 궁금합니다. 당시 나는 그렇지 않다고 언급했다. 그러나 Chrome이 버전의 런타임에 따라 런타임의 특정 영역에서 이상한 성능 향상을 얻는 것은 들어 본 적이 없습니다.
Qix-MONICA가 MISTREATED

여기에 약간 오래된 스레드가 있지만, 내가 읽은 것에서 직접 추적했다고 주장하지는 않지만 JSON.parse는 실제로 eval이 최종 단계에서 입력됩니다. 따라서 효율성 측면에서 더 많은 작업 / 시간이 필요합니다. 그러나 보안 측면에서 왜 구문 분석하지 않습니까? eval은 멋진 도구입니다. 다른 방법이없는 것들에 사용하십시오. JSON을 통해 함수를 전달하려면 평가없이 수행하는 방법이 있습니다. JSON.stringify의 두 번째 매개 변수를 사용하면 콜백을 실행하여 typeof가 함수인지 확인할 수 있습니다. 그런 다음 함수의 .toString ()을 가져옵니다. 당신이 검색하면 이것에 대한 좋은 기사가 있습니다.
jdmayfield


4

사용자가 논리 함수를 입력하고 AND OR을 평가하도록하려면 JavaScript 평가 함수가 완벽합니다. 나는 두 개의 문자열을 받아 들일 수 있습니다 eval(uate) string1 === string2.


Function () {}을 (를) 사용할 수도 있지만, 서버에서이 서버를 사용하지 않으려면 서버에서이 기능을 사용할 때주의하십시오.
aoeu256

3

코드에서 eval ()의 사용을 발견하면“eval ()은 악하다”라는 진언을 기억하십시오.

이 함수는 임의의 문자열을 받아서 JavaScript 코드로 실행합니다. 문제의 코드를 미리 알고 있으면 (런타임에 결정되지 않음) eval ()을 사용할 이유가 없습니다. 런타임에 코드가 동적으로 생성되면 eval ()없이 목표를 달성하는 더 좋은 방법이 종종 있습니다. 예를 들어 대괄호 표기법을 사용하여 동적 속성에 액세스하는 것이 더 좋고 간단합니다.

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

사용 eval()이 변조 된 (네트워크에서 오는 예를 들어) 코드를 실행 할 수 있기 때문에, 보안 문제를 가지고도. 이것은 Ajax 요청의 JSON 응답을 처리 할 때 일반적인 반 패턴입니다. 이러한 경우 브라우저의 내장 메소드를 사용하여 JSON 응답을 구문 분석하여 안전하고 유효한지 확인하는 것이 좋습니다. 지원하지 않는 브라우저JSON.parse()기본적으로 JSON.org의 라이브러리를 사용할 수 있습니다.

문자열을 setInterval(),에 전달 setTimeout()하면 Function()생성자가 대부분 사용 eval()과 비슷 하므로 피해야합니다.

배후에서 JavaScript는 여전히 프로그래밍 코드로 전달한 문자열을 평가하고 실행해야합니다.

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

new Function () 생성자를 사용하는 것은 eval ()과 유사하며주의해서 접근해야합니다. 그것은 강력한 구조 일 수 있지만 종종 오용됩니다. 당신이 절대적으로 사용해야하는 경우eval() 대신 new Function () 사용을 고려할 수 있습니다.

new Function ()에서 평가 된 코드가 로컬 함수 범위에서 실행되므로 평가중인 코드에서 var로 정의 된 모든 변수가 자동으로 전역 변수가되지 않기 때문에 잠재적 인 이점이 거의 없습니다.

자동 전역을 방지하는 또 다른 방법은 eval()통화를 즉시 기능 으로 묶는 것입니다 .


eval없이 함수 로컬 동적 변수 이름을 평가하는 방법을 제안 할 수 있습니까? Eval (및 이와 유사한) 함수는 대부분의 언어에서 마지막 함수이지만, 때로는 필요합니다. 동적 변수의 이름을 얻는 경우 더 안전한 솔루션은 무엇입니까? 어쨌든 자바 스크립트 자체는 실제 보안을위한 것이 아닙니다 (서버 측은 분명히 주요 방어 수단입니다). 관심이 있으시다면 여기에 eval 사용 사례가 있습니다. stackoverflow.com/a/48294208
Regular Joe

2

사용자가 제출 한 코드를 실행하는 경우 가능한 보안 문제 외에도 대부분의 경우 코드를 실행할 때마다 코드를 구문 분석하지 않는 더 좋은 방법이 있습니다. 익명 함수 또는 객체 속성은 대부분의 평가 사용을 대체 할 수 있으며 훨씬 안전하고 빠릅니다.


2

차세대 브라우저에 약간의 JavaScript 컴파일러가 등장함에 따라 이는 더 큰 문제가 될 수 있습니다. Eval을 통해 실행 된 코드는 이러한 최신 브라우저에 대해 나머지 JavaScript만큼 성능이 떨어질 수 있습니다. 누군가 프로파일 링을해야합니다.


2

이것은 평가에 대해 이야기하고 악이 아닌 방법에 대해 이야기하는 좋은 기사 중 하나입니다 : http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

나는 당신이 밖으로 나가서 eval () 사용을 시작해야한다고 말하는 것이 아닙니다. 실제로 eval ()을 실행하기위한 좋은 사용 사례는 거의 없습니다. 코드 명확성, 디버깅 가능성 및 간과해서는 안되는 성능에 대한 우려가 있습니다. 그러나 eval ()이 의미가있는 경우이를 사용하는 것을 두려워해서는 안됩니다. 먼저 사용하지 말고 eval ()을 적절하게 사용할 때 코드가 더 취약하거나 안전하지 않다고 생각하지 않도록하십시오.


2

eval ()은 매우 강력하며 JS 문을 실행하거나 표현식을 평가하는 데 사용할 수 있습니다. 그러나 질문은 eval ()의 사용에 관한 것이 아니라 eval ()으로 실행하는 문자열이 악의적 인 당사자에 의해 어떻게 영향을 받는지 간단히 말해줍니다. 결국 악성 코드가 실행됩니다. 힘으로 큰 책임이 따른다. 따라서 현명하게 사용하십시오. 이것은 eval () 함수와 관련이 없지만이 기사에는 꽤 좋은 정보가 있습니다. http://blogs.popart.com/2009/07/javascript-injection-attacks/ eval ()의 기본을 찾고 있다면 여기를보십시오 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval


2

JavaScript 엔진에는 컴파일 단계에서 수행하는 여러 가지 성능 최적화 기능이 있습니다. 이 중 일부는 코드가 실행될 때 기본적으로 코드를 정적으로 분석하고 모든 변수 및 함수 선언이있는 위치를 미리 결정하여 실행 중에 식별자를 확인하는 데 드는 노력을 덜하게됩니다.

그러나 엔진이 코드에서 eval (..)을 찾으면 본질적으로 식별자 위치에 대한 모든 인식이 유효하지 않은 것으로 가정해야합니다. 여기서 eval (..)에 전달할 코드를 정확히 알 수 없기 때문입니다. 어휘 범위 또는 수정하려는 새로운 어휘 범위를 만들기 위해 전달할 수있는 객체의 내용을 수정합니다.

다시 말해서 비관적 의미에서 eval (..)이 있으면 최적화하는 것이 무의미하므로 단순히 최적화를 전혀 수행하지 않습니다.

이것은 모든 것을 설명합니다.

참고 :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance


100 % 보장 된 코드에서 Javascript 엔진을 찾아 평가할 수 없습니다. 따라서 언제든지 준비가되어 있어야합니다.
잭 지핀

2

항상 나쁜 생각은 아닙니다. 코드 생성을 예로 들어 보겠습니다. 필자는 최근 virtual-domhandlebars 의 격차를 해소하는 Hyperbars 라는 라이브러리를 작성했습니다 . 핸들 바 템플릿을 구문 분석하고 이후 가상 -dom에서 사용하는 하이퍼 스크립트 로 변환하여이를 수행합니다 . 하이퍼 스크립트는 먼저 문자열로 생성되며 반환하기 전에 실행 코드로 변환합니다. 나는 이 특정한 상황에서 악의 정반대를 발견 했다.eval()eval()

기본적으로

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

이에

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()생성 된 문자열을 한 번만 해석 한 다음 실행 가능한 출력을 여러 번 재사용해야하므로 이와 같은 상황에서는 성능이 문제가되지 않습니다.

당신은 당신이 궁금하면 코드 생성이 달성 방식을 볼 수 있습니다 여기에 .


2

eval()브라우저에서 실행되는 자바 스크립트에서 사용하면 실제로 중요하지 않다고 말하면 됩니다. * (caveat)

모든 최신 브라우저에는 어쨌든 임의의 자바 스크립트를 실행할 수있는 개발자 콘솔이 있으며 모든 세미 스마트 개발자는 JS 소스를보고 개발자 콘솔에 필요한 비트를 넣어 원하는대로 할 수 있습니다.

* 서버 엔드 포인트가 사용자 제공 값의 올바른 유효성 검사 및 위생 처리를하는 한, 클라이언트 측 자바 스크립트에서 구문 분석되고 평가되는 내용은 중요하지 않습니다.

eval()그러나 PHP 에서 사용하기 에 적합한 지 묻는다면 eval 문에 전달 될 수있는 값을 허용 하지 않는 한 대답은 NO 입니다.


개발자 콘솔이있을뿐만 아니라 URL 막대에 javascript : code를 입력하여 페이지에 자체 개발자 콘솔을 만들 수 있습니다 (예전 IE 브라우저 및 모바일 장치의 경우).
Dmitry

1

나는 지금까지 언급 한 것을 반박하려고 시도하지는 않지만, 내가 알고있는 한 다른 방법으로는 할 수없는 eval () 사용을 제공 할 것입니다. 이것을 코딩하는 다른 방법과 아마도 그것을 최적화하는 방법이있을 수 있지만, 이것은 실제로 다른 대안이없는 eval의 사용을 설명하기 위해 명확하게하기 위해 종소리와 휘파람없이 오랫동안 수행되었습니다. 즉, 프로그래밍 방식으로 생성 된 동적으로 (보다 정확한) 객체 이름 (값이 아닌)입니다.

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

편집 : 그건 그렇고, 나는 (당신이 지적한 모든 보안상의 이유로) 사용자 입력에 객체 이름을 기반으로한다고 제안하지는 않습니다. 나는 당신이 그렇게하고 싶은 좋은 이유를 상상할 수 없습니다. 아직도, 나는 그것이 좋은 생각이 아니라고 지적 할 것이라고 생각했다 :)


3
이것 namespaceToTest[namespaceParts[i]]으로 eval을 수행 할 필요가 없습니다 if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};.else namespaceToTest = namespaceToTest[namespaceParts[i]];
user2144406

1

가비지 콜렉션

브라우저 가비지 콜렉션은 평가 된 코드를 메모리에서 제거 할 수 있는지 여부를 모릅니다. 따라서 페이지를 다시로드 할 때까지 코드를 저장 상태로 유지합니다. 사용자가 곧 페이지에 있으면 웹앱에 문제가 될 수 있습니다.

다음은 문제를 보여주는 스크립트입니다.

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

위의 코드만큼 간단한 것은 앱이 죽을 때까지 적은 양의 메모리가 저장되도록합니다. 회피 된 스크립트가 거대한 함수이고 간헐적으로 호출 될 때 이것은 더 나쁩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.