Являются ли eval () и новая функция () одним и тем же?


эти две функции делают то же самое за кулисами? (в функции одного оператора)

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

7 ответов:

нет, они не то же самое.

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

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

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

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

нет.

в вашем обновлении, звонки на 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');

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

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

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

редактировать ниже:

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

1 + 1

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

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

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

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

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

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

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

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

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

функция имеет разную область выполнения с вызывающим абонентом, eval имеют то же самое. Но это правило действует только до ES6, в ES6 и будущем eval имеют одинаковое поведение с функцией.