답변:
내가 JScript 엔진을 구현했을 때 나는 EVAL IS EVIL 셔츠를 인쇄하는 것을 옹호 했지만 슬프게도 우리는 결코 그것을 피하지 못했습니다.
eval의 가장 큰 문제는 명백한 악성 코드 삽입 공격이 아니라는 점입니다. 그것의 가장 큰 문제는 사람들이 작은 문제를 해결하기 위해 그것을 정말로 큰 망치로 사용하는 경향이 있다는 것입니다. JScript 팀에있을 때 "eval"에 대해 실제로 본 대부분의 실제 사용법은 조회 테이블을 사용하여 간단하게 해결할 수있었습니다. JScript의 모든 객체는 이미 조회 테이블 이기 때문에 부담이되지 않았습니다. 평가는 다시 컴파일러를 시작 하고 완전히 코드를 최적화 할 수있는 컴파일러의 기능을 파괴한다 .
이 맥락에서 더 많은 생각을하려면 2003 년 주제에 관한 저의 기사를보십시오 :
일반적인 악 :
http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx
주입 공격 악 :
http://blogs.msdn.com/b/ericlippert/archive/2003/11/04/53335.aspx
eval()
입니다 하지 클라이언트 (브라우저) 코드에 보안 위험.
대부분의 보안 허점은 SQL 인젝션과 같은 종류의 허점, 즉 사용자 입력을 JavaScript 코드로 연결합니다. 차이점은 SQL에서 이런 일이 발생하지 않도록하는 방법이 있지만 JavaScript로 할 수있는 일은 많지 않다는 것입니다.
사소하고 쓸모없는 예로써, 간단한 JavaScript 계산기 :
textbox1.value = eval(textbox2.value);
올바른 사용 예 중 하나는 일반적인 단어를 뽑아서 짧은 1-2 문자로 바꾸어 JavaScript를 압축하는 일부 JavaScript 패커입니다. 그런 다음 패커는 생성 된 사전을 기반으로 문자열 대체 코드와 함께이 모든 것을 출력 한 다음 결과를 회피합니다.
평가 후면 같은 기능이없는 JS에서 할 불가능 몇 가지가 있습니다 ( eval
, Function
, 어쩌면 그 이상).
가지고 apply
예를 들어. 일반 함수 호출에서 사용할 때 사용하기 쉽습니다.
foo.apply(null, [a, b, c])
그러나 새로운 구문을 통해 생성하는 객체에 대해서는 어떻게해야합니까?
new Foo.apply(null, [a, b, c])
작동하지 않거나 유사한 형태가 아닙니다.
그러나 eval
또는 Function
( Function
이 예제에서 사용) 을 통해이 제한을 해결할 수 있습니다 .
Function.prototype.New = (function () {
var fs = [];
return function () {
var f = fs[arguments.length];
if (f) {
return f.apply(this, arguments);
}
var argStrs = [];
for (var i = 0; i < arguments.length; ++i) {
argStrs.push("a[" + i + "]");
}
f = new Function("var a=arguments;return new this(" + argStrs.join() + ");");
if (arguments.length < 100) {
fs[arguments.length] = f;
}
return f.apply(this, arguments);
};
}) ();
예:
Foo.New.apply(null, [a, b, c])
;
물론, Function.prototype.New
사용 하는 함수를 수동으로 만들 수 는 있지만,이 장황하고 복잡 할뿐만 아니라 (정의 적으로) 유한해야합니다. Function
코드가 여러 인수에 대해 작동하도록 허용합니다.
eval()
? "
나는 거의 사용되지 않아야한다는 것에 동의하지만에 대한 강력한 사용 사례를 찾았습니다 eval
.
Firefox에는 asm.js라는 실험적인 새로운 기능이 있습니다. Javascript 언어의 제한된 하위 집합을 기본 코드로 컴파일 할 수 있습니다. 예, 이것은 매우 훌륭하지만 한계가 있습니다. Javascript의 제한된 하위 집합을 Javascript에 포함 된 C와 같은 언어로 생각할 수 있습니다. 실제로 사람이 읽거나 쓰는 것은 아닙니다.
Javascript의이 제한된 서브 세트는 컴파일 된 코드에서 런타임 생성 코드를 컴파일 된 코드에 삽입 할 수 없습니다.
사용자가 친숙한 표기법으로 수학 표현식을 작성하고 즉시 asm.js 코드로 변환 할 수있는 코드를 작성했습니다. 서버 측에서 코드를 처리하고 싶지 않다면 (필자가 아닌) eval
브라우저에서 결과 코드를 실시간으로 처리 할 수있는 유일한 도구입니다.
다른 사람들이 지적했듯이, 작업 할 때 가장 중요한 것은 eval
안전하게 유지하는 것입니다. 이를 위해서는 인수 검사를 철저히 수행 eval
하고 런타임 생성 코드를 유지하고 보호하는 것이 일반적으로 훨씬 어렵 기 때문에 코드를 단순하게 유지하려고합니다.
즉, 나는 eval
두 가지 종류의 것을 사용 하는 것을 즐깁니다 (아마도 더 좋고 덜 악의적 인 대안이있을지라도).
eval
"명시 적으로 캐싱 코드"방법 이므로 성능을 향상시키는 데 사용할 수 있습니다. 옵티마이 저는 항상 개선되고 있지만, 그들이 당신을 위해 무엇을 할 수 있는지에 대한 보장은 없습니다. 코드에서 일을 명시 적으로 지정하면 실제로 옵티마이 저가보다 현명한 결정을 내릴 수 있습니다.예를 들어, 이 사전 컴파일 된 객체 반복자 접근 방식eval
은 객체 속성 반복에 사용할 때 명확한 성능 이점을 보여줍니다 . 또한 비용이 거의 들지 않으면서도 암시 적 제약 조건 검사 및 그 이상을 제공 할 수있는 강력한 유형 시스템의 시작을 보여줍니다.
많은 노련한 Javascript 개발자는 아마도 이것이 토끼 구멍이라고 지적 할 것입니다. Javascript를 이런 식으로 작성하기 시작하면 언어 사용 방식을 근본적으로 변경하기 때문입니다. 그러나 자바 스크립트를 좋아하는 사람들에게는 반드시 나쁜 것은 아니지만 언어 자체의 사용 방식을 변경해야만 달성 할 수있는 기본 언어 기능이 누락되었습니다.
eval이 갈 길처럼 보이는 상황이 있는데 문자열을 평가하고 이름이 문자열과 동일한 기존 변수를 반환합니다.
table1ResultsTable, table2ResultsTable, tableNResultsTable과 같은 여러 테이블이 있습니다. jQuery 데이터 테이블 객체와 같은 이름으로 변수를 설정했습니다. 이를 사용하여 테이블을 설정하고 jQuery 데이터 테이블 함수를 호출합니다.
각 테이블에는 class = "resultsTable"이 할당되어 있습니다. 이제 테이블을 클릭 할 때 변수를 가져와야합니다. 나는 이것을하고있다 :
$('resultsTable).on('click', 'td', function(event) {
var cResultsTable = eval(event.target.parentElement.parentElement.parentElement.id);
[etc]
});
그래서 셀을 클릭 한 테이블의 id를 얻습니다.이 테이블은 해당하는 datatable 객체 변수와 동일한 이름을 갖습니다. 누군가 개선에 대한 제안이 있으면 그것에 대해 알고 싶습니다.
event.target.parentElement.parentElement.parentElement
끔찍하다. 또한, 평가 가능한 ID를 의도적으로 사용하지 않는 한 (참조 오류 : [id] 정의되지 않음 ") 오류를 eval 호출로 생성 할 것으로 예상됩니다. 중복 ID 생성).
document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE
. Eric Lippert가 지적했듯이 "JScript의 모든 객체는 이미 조회 테이블입니다."
eval
JSPacker와 같은 응용 프로그램이 좋아하는 방식으로 큰 코드 덩어리에 대해 어떻게 생각 하십니까? JSPacker + gzip은 일반적으로 자체 솔루션보다 파일 크기가 작지만, 올바르게 지적했듯이 본질적으로 동일한 코드에서 컴파일러를 두 번 실행하고 문자열 대체를 수행하는 오버 헤드가 발생합니다.