Почему использование JavaScript-функции eval - плохая идея? - PullRequest
502 голосов
/ 17 сентября 2008

Функция eval - это мощный и простой способ динамического генерирования кода, так что же такое предостережения?

Ответы [ 25 ]

2 голосов
/ 17 сентября 2008

Это может стать более серьезной проблемой, так как браузеры следующего поколения выпускают некоторые разновидности JavaScript-компилятора. Код, выполняемый через Eval, может не работать так же хорошо, как и остальная часть вашего JavaScript на этих новых браузерах. Кто-то должен сделать некоторое профилирование.

1 голос
/ 01 марта 2018

Я бы сказал, что не имеет значения, если вы используете eval() в javascript, который запускается в браузерах. * (Предостережение)

Все современные браузеры имеют консоль разработчика, где вы в любом случае можете выполнить произвольный javascript, и любой полуумный разработчик может взглянуть на ваш JS-источник и поместить все нужные ему кусочки в консоль разработчика, чтобы сделать то, что он желает.

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

Если вы спросите, подходит ли для использования eval() в PHP, ответ будет NO , если вы не белый список любых значений, которые могут быть переданы вашему заявлению eval .

1 голос
/ 28 ноября 2016

Это не всегда плохая идея. Взять, к примеру, генерацию кода. Недавно я написал библиотеку под названием Hyperbars , которая ликвидирует разрыв между virtual-dom и рулем . Это делается путем анализа шаблона руля и преобразования его в гиперсценарий , который впоследствии используется virtual-dom. Гиперскрипт сначала генерируется в виде строки, а перед его возвратом eval() превращает его в исполняемый код. В этой конкретной ситуации я обнаружил eval() полную противоположность злу.

В основном с

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

К этому

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

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

Вы можете увидеть, как была достигнута генерация кода, если вам интересно здесь .

1 голос
/ 30 января 2016

JavaScript Engine имеет ряд оптимизаций производительности, которые он выполняет на этапе компиляции. Некоторые из них сводятся к тому, что можно по существу статически анализировать код в процессе его лексического анализа и заранее определять, где находятся все объявления переменных и функций, так что требуется меньше усилий для разрешения идентификаторов во время выполнения.

Но если Механизм находит в коде eval (..), он, по сути, должен предположить, что вся его осведомленность о местоположении идентификатора может быть недействительной, потому что он не может точно знать, в какой момент лексинга, какой код вы можете передать eval ...) для изменения лексической области или содержимого объекта, с которым вы можете передавать, для создания новой лексической области, к которой следует обращаться.

Другими словами, в пессимистическом смысле большинство тех оптимизаций, которые он сделал бы, бессмысленно, если присутствует eval (..), поэтому он просто не выполняет оптимизацию вообще.

Это все объясняет.

Ссылка:

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

1 голос
/ 12 февраля 2015

Я не буду пытаться опровергнуть все, что было сказано ранее, но я предложу использовать eval (), который (насколько я знаю) не может быть реализован каким-либо другим способом. Вероятно, есть другие способы кодирования этого и, возможно, способы его оптимизации, но это делается от руки и без наворотов для ясности, чтобы проиллюстрировать использование eval, у которого действительно нет других альтернатив. То есть: динамические (или точнее) программно созданные имена объектов (в отличие от значений).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

РЕДАКТИРОВАТЬ: кстати, я бы не советовал (по всем причинам безопасности, указанным выше), чтобы вы основывали свои имена объектов на пользовательском вводе. Я не могу представить себе вескую причину, по которой вы захотите это сделать. Тем не менее, подумал, что укажу, что это не будет хорошей идеей:)

...