Являются ли eval() и new Function() одинаковыми?
Эти две функции выполняют одно и то же за кулисами? (в одиночных функциях оператора)
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'));
Ответы
Ответ 1
Нет, они не одинаковы.
-
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
на ненадежных данных небезопасно и неразумно.
Ответ 2
Нет.
В вашем обновлении вызовы 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');
Ответ 3
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]');
}
Самая большая разница между этой и новой функцией заключается в том, что функция не лексически ограничена. Таким образом, у него не было бы доступа к переменным закрытия и моим.
Ответ 4
Если вы имеете в виду, он даст одинаковые результаты, тогда да... но просто для eval (иначе, "оцените эту строку JavaScript" ) было бы намного проще.
EDIT Ниже:
Мне нравится говорить... эти две математические проблемы одинаковы:
1 + 1
1 + 1 + 1 - 1 + 1 - 1 * 1/1
Ответ 5
В этом примере результаты одинаковы, да. Оба выполняют переданное вами выражение. Это делает их настолько опасными.
Но они делают разные вещи за пределами. Тот, который включает new Function()
, за кадром, создает анонимную функцию из кода, который вы поставляете, который выполняется при вызове функции.
JavaScript, который вы передаете ему, технически не выполняется, пока вы не вызываете анонимную функцию. Это контрастирует с eval()
, который сразу же выполняет код и не генерирует на нем функцию.
Ответ 6
Просто хочу указать некоторый синтаксис, используемый в примерах здесь, и что это означает:
var func = function(string) {
return (new Function( 'return (' + string + ')' )());
}
обратите внимание, что функция (...)() имеет конец "()" в конце. Этот синтаксис вызовет функцию func для выполнения новой функции и возвращает строку, а не функцию, возвращающую строку, но если вы используете следующее:
var func = function(string) {
return (new Function( 'return (' + string + ')' ));
}
Теперь func вернет функцию, которая возвращает строку.