Являются ли eval () и new Function () одинаковыми? - PullRequest
81 голосов
/ 05 января 2011

Эти две функции выполняют за кулисами одно и то же? (в функциях с одним оператором)

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'));

Ответы [ 6 ]

106 голосов
/ 05 января 2011

Нет, они не одинаковы.

  • eval() оценивает строку как выражение JavaScript в текущей области выполнения и может обращаться к локальным переменным.
  • new Function() анализирует код JavaScript, хранящийся в строке, в объект функции, который затем может быть вызван. Он не может получить доступ к локальным переменным, потому что код выполняется в отдельной области видимости.

Рассмотрим этот код:

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

Если используется new Function('return (a = 22);')(), локальная переменная a сохранит свое значение. Тем не менее, некоторые программисты на JavaScript, такие как Дуглас Крокфорд, считают, что ни один не должен использоваться , если не является абсолютно необходимым , а вычисление / использование конструктора Function для ненадежных данных небезопасно и неразумно.

6 голосов
/ 05 января 2011

new Function создает функцию, которую можно использовать повторно.eval просто выполняет заданную строку и возвращает результат последнего оператора.Ваш вопрос введен в заблуждение, когда вы пытались создать функцию-оболочку, которая использует функцию для эмуляции eval.

Правда ли, что они разделяют некоторый код за кулисами?Да, очень вероятно.Точно такой же код?Нет, конечно.

Для забавы, вот моя собственная несовершенная реализация, использующая 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]');
}

Самое большое различие между этой и новой функцией заключается в том, что функция не имеет лексической области действия.Так что у него не будет доступа к переменным замыкания, а у меня будет.

6 голосов
/ 05 января 2011

Нет.

В вашем обновлении вызовы 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');
2 голосов
/ 05 января 2011

Если вы имеете в виду, даст ли он те же результаты, то да ... но просто eval (иначе, "оценить эту строку JavaScript") будет намного проще.

РЕДАКТИРОВАТЬ Ниже:

Это все равно что сказать ... эти две математические задачи одинаковы:

1 + 1

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

1 голос
/ 13 июня 2013

Просто хочу указать на некоторый синтаксис, используемый в примерах, здесь и что это означает:

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

обратите внимание, что функция (...) () имеет в конце "()".Этот синтаксис заставит func выполнить новую функцию и вернуть строку, а не функцию, которая возвращает строку, но если вы используете следующее:

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

Теперь func вернет функцию, которая возвращает строку.

1 голос
/ 05 января 2011

В этом примере результаты одинаковы, да. Оба исполняют переданное вами выражение. Это то, что делает их такими опасными.

Но они делают разные вещи за кулисами. Тот, который включает new Function(), скрытно, создает анонимную функцию из предоставленного вами кода, который выполняется при ее вызове.

JavaScript, который вы передаете ему, технически не выполняется, пока вы не вызовете анонимную функцию. Это в отличие от eval(), который выполняет код сразу и не генерирует функцию на его основе.

...