MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

현재 번역은 완벽하지 않습니다. 한국어로 문서 번역에 동참해주세요.

eval() 은 문자로써 표현된 JavaScript 코드를 실행하는 메소드이다.

문법

eval(string)

파라미터

string
JavaScript 표현식, 문장(statement), 연속적인 문장들을 나타내는 문자열이다. 표현식은 존재하는 객체들의 프로퍼티들과 변수들을 포함할 수 있다.

설명

eval() 은 전역 객체의 함수 프로퍼티 이다.

eval() 함수의 인자는 문자열이다. 만약에 문자열이 표현식을 나타낸다면, eval() 은 표현식을 실행한다. 만약에 인자가 하나 이상의 JavaScript 문을 나타낸다면, eval() 은 문장들을 실행한다. 연산식을 계산하기 위해 eval() 을 호출하지 마라. JavaScript 는 자동으로 연산식을 계산한다.

당신이 문자열로 연산식을 구성한다면, 나중에 그 식을 계산하기 위해 eval() 을 사용할 수 있다. 예를 들어, x 라는 변수가 있다고 가정하자.  당신은 스크립트 내에서 "3 * x + 2" 이라는 표현식 문자열을 변수에 할당하고, 그 다음 eval() 을 나중에 호출함으로써 x 가 포함된 표현식의 수행을 연기할 수 있다. 

eval() 의 인자가 문자열이 아니면, eval() 은 인자를 변환하지 않고 반환한다. 다음의 예시에서, String 생성자가 명시되어 있으면 eval() 은 문자열을 계산하기 보다는 String 객체를 반환한다.

eval(new String("2 + 2")); // "2 + 2" 인 문자열 객체를 반환
eval("2 + 2");             // 4을 반환

당신은 toString() 을 사용하는 일반적인 방식으로 이 제약을 피할 수 있다.

var expression = new String("2 + 2");   
eval(expression.toString());           // 4을 반환

eval 외에 참조를 통해 eval 함수를 호출하여 간접적으로 사용한다면, ECMAScript 5 부터는 지역 스코프 대신 전역 스코프 에서 동작한다. 예를 들어, 함수 선언은 전역 함수를 생성한다는 의미이며, 수행 될 코드는 그것이 호출 될 스코프 내의 지역 변수에 접근하지 않는다는 것을 의미한다.

function test() {
  var x = 2, y = 4;
  console.log(eval("x + y"));  // 직접 호출은 지역 스코프를 사용하며, 결과는 6이다
  var geval = eval;
  console.log(geval("x + y")); // 간접 호출은 전역 스코프를 사용하며, `x` 가 정의되지 않았기 때문에 ReferenceError 를 던진다.
}

불필요하게 eval 을 사용하지 마라!

eval() 은 caller 의 특권으로 통과한 코드를 수행하는 위험한 함수이다. 당신이 악의적인 영향을 받을 수 있는 문자열을 eval() 로 실행한다면, 당신의 웹페이지 / 확장프로그램의 허가를 가지는 사용자의 기계에서 악의적인 코드를 수행하게 될 것이다. 더 중요한건,  제 3의 코드가 eval() 이 적용된 스코프를 볼 수 있으며, 이것이 비슷한 Function 은 민감하지 않다는 면에서 공격 가능성을 야기할 수 있다.

또한 eval() 은 요즘 JS 엔진에 의해 최적화된 많은 다른 구조들에 비해, JS interpreter 를 적용해야 하기 때문에, 일반적으로 대안들보다 느리다.

eval() 의 일반적인 사용법을 위한 안전한 (그리고 빠른!) 대안이 있다.

멤버 프로퍼티들의 접근

당신은 프로퍼티들 내에서 프로퍼티 명을 변환하기 위해 eval() 을 사용해선 안된다. 코드가 실행될 때까지 접근될 객체의 프로퍼티가 알려져 있지 않은 다음의 예제를 고려해라. 이것은 eval 과 함께 사용될 수 있다:

var obj = { a: 20, b: 30 };
var propname = getPropName();  // "a" 또는 "b" 를 반환

eval( "var result = obj." + propname );

그러나, eval() 은 여기에 불필요하다. 사실, 여기서 그것을 사용하는 것은 말릴 일이다. 대신, 훨씬 빠르고 안전한 property accessors 를 사용해라:

var obj = { a: 20, b: 30 };
var propname = getPropName();  // "a" 또는 "b" 를 반환
var result = obj[ propname ];  //  obj[ "a" ] 는 obj.a 와 동일함

단편적인 코드 수행 대신 함수를 사용

JavaScript 는 함수를 다른 API의 파라미터로 전달할 수 있고, 다른 객체의 프로퍼티나 변수에 저장할 수 있는 등의 1급 함수를 가진다. 많은 DOM API들이 이 점을 염두하여 설계되며, 그래서 당신은 쓸 수 있다(써야 한다). 

// setTimeout(" ... ", 1000) 대신에 사용:
setTimeout(function() { ... }, 1000); 

// elt.setAttribute("onclick", "...") 대신에 사용:
elt.addEventListener("click", function() { ... } , false); 

또한 클로저는 연결된 문자열 없이 매개 변수화 된 함수들을 생성하는데 유용하다. 

JSON 파싱 (문자열을 JavaScript 객체로 변환)

만약 당신이 eval() 을 호출하려는 문자열에 코드가 아니라 데이터가 포함되어 있다면, (예를 들어, 배열: "[1, 2, 3]"), 당신은 JSON으로 변환하는 것을 고려해야 한다. 이것은 문자열이 데이터를 대신하기 위해 JavaScript 문법의 일부를 사용하는 것을 허용한다. 또한 Downloading JSON and JavaScript in extensions 를 보자.

JSON 문법이 JavaScript 문법에 비해 제약이 있기 때문에, 많은 유효한 JavaScript 리터럴은 JSON 으로 변환하지 않을 것이다. 예를 들어, 콤마의 연속은 JSON 으로 허용되지 않고, 객체 리터럴에서 프로퍼티 명(키)은 반드시  따옴표로 감싸야 한다. 추후 JSON 으로 변환될 문자열을 만들어 내기 위해 JSON serializer(직렬변환기) 를 사용하자. 

코드 대신에 데이터 전달

예를 들어, 웹 페이지의 컨텐츠를 스크랩 하기 위해 설계된 확장 프로그램은 JavaScript 코드 대신 XPath 에 스크랩 규칙을 가질 수 있을 것이다.

제한된 특권으로 코드 실행

당신이 코드를 실행시켜야 한다면, 축소한 특권으로 실행하도록 고려해라. 이 조언은 주로 확장 프로그램이나 XUL 어플리케이션에 적용되며, 이에 Components.utils.evalInSandbox 를 사용할 수 있다. 

예제

eval 사용하기

다음의 코드에서, eval() 를 포함하는 문들은 모두 42를 반환한다. 첫번째는 "x + y + 1" 문자열을 수행한다; 두번째는 "42" 라는 문자열을 수행한다.

var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // 42 를 반환
eval(z);           // 42 를 반환

JavaScript 문 문자열을 수행하기 위해 eval  사용하기

다음의 예제에서 str 문자열을 수행하기 위해 eval() 을 사용한다. 이 문자열은 x 가 5이면 console 에 로그를 남긴 다음 z 에 42 를 할당하고, 그 밖의 경우에는 z 에 0 을 할당하는 JavaScript 문들로 구성되어 있다. 두 번째 문이 실행되면, eval() 은 이 문들이 수행되도록 할 것이고, 문들의 집합을 수행할 것이고, z 에 할당된 값을 반환할 것이다.

var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0; ";

console.log("z is ", eval(str));

마지막 표현식이 수행된다

eval() 은 마지막 표현식의 수행된 값을 반환한다.

var str = "if ( a ) { 1+1; } else { 1+2; }";
var a = true;
var b = eval(str);  // 2를 반환
 
console.log("b is : " + b);

a = false;
b = eval(str);  // 3을 반환

console.log("b is : " + b);

함수 정의 문자열로써의 eval 은 "(" 와 ")" 가 필요하다 

var fctStr1 = "function a() {}"
var fctStr2 = "(function a() {})"
var fct1 = eval(fctStr1)  // undefined 을 반환
var fct2 = eval(fctStr2)  // 함수를 반환

명세서

명세 상태 내용
ECMAScript 1st Edition (ECMA-262) Standard 최초 정의.
ECMAScript 5.1 (ECMA-262)
The definition of 'eval' in that specification.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'eval' in that specification.
Standard  
ECMAScript 2017 Draft (ECMA-262)
The definition of 'eval' in that specification.
Draft  

브라우저 호환성

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) (Yes) (Yes)
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)

Gecko-specific notes

  • 역사적으로 eval() 은 수행될 context 를 지정하는 선택적인 두 번째 인자가 있었다. 이 인자는 비 표준이었고, Gecko 1.9.1 (Firefox 3.5) 에 SpiderMonkey 로부터 제거되었다. bug 442333 를 보자.

참고

문서 태그 및 공헌자

 이 페이지의 공헌자: desty, nicesh
 최종 변경: desty,