Почему использование функции eval в JavaScript - плохая идея?

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

Не будь eval () Саймоном Уиллисоном - 24ways.org/2005/dont-be-eval

Brian Singh 17.09.2008 23:40

Как указано в moduscreate.com/javascript-performance-tips-tricks - (new Function (str)) () более производительна, чем eval (str). Всего мои 2 цента :)

Grgur 02.08.2012 19:05

очевидно, новая функция (a) на 67% медленнее, чем eval (a) на chrome

what is sleep 11.12.2013 00:35

для меня новые функции (а) на 80% медленнее последней версии Chrome на osx

john Smith 26.01.2014 14:35

Я добавил статическую функцию, просто чтобы сравнить производительность. jsperf.com/eval-vs-new-function/2

Nepoxx 28.08.2014 21:06

те же предостережения, что и include и require в PHP. eval также можно назвать "include_from_string" или "runtime_compile". Мало того, что это не зло, но я уверен, что это одна из фундаментальных причин создания сценариев - гораздо проще создать сценарий, который приближается к объекту, и начать его использовать / изменять без перекомпиляции, чем перекомпилировать DLL каждый раз. раз вам нужны перемены. С точки зрения высокого уровня Eval - это то же самое, что компилировать файл c в DLL, затем вызывать его «точку входа» и связываться с его »символом состояния (или заставить точку входа вернуть объект состояния).

Dmitry 02.06.2018 23:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
552
6
263 114
26
Перейти к ответу Данный вопрос помечен как решенный

Ответы 26

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

Какая же тогда альтернатива?

moderns 12.05.2014 18:06

На самом деле альтернатива - просто написать код, который этого не требует. Крокфорд подробно рассказывает об этом, и, если вам нужно его использовать, он в значительной степени говорит, что это недостаток дизайна программы и его необходимо переделать. По правде говоря, я тоже с ним согласен. JS, несмотря на все его недостатки, действительно гибок и позволяет сделать его гибким.

kemiller2002 12.05.2014 18:46

но когда вы получите ответ от сервера с помощью AJAX, вы получите текст ответа xmlHttp.responseText, и вам нужно будет использовать eval для его выполнения.

moderns 12.05.2014 18:47

Неправда, у большинства фреймворков есть метод анализа JSON, и если вы не используете фреймворк, вы можете использовать JSON.parse (). Большинство браузеров поддерживают его, и если вы действительно в затруднительном положении, вы можете довольно легко написать парсер для JSON.

kemiller2002 12.05.2014 18:58

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

user2867288 04.02.2015 17:37

Дело в том, что мне проще внедрить код в ваш браузер. Допустим, вы используете eval в строке запроса. Если я обманом заставлю вас щелкнуть ссылку, ведущую на этот сайт с прикрепленной строкой запроса, то теперь я выполнил свой код на вашем компьютере с полным разрешением браузера. Я хочу записывать в журнал все, что вы вводите на этом сайте, и отправлять мне? Готово, и меня не остановить, потому что при выполнении eval браузер дает ему наивысшие полномочия.

kemiller2002 04.02.2015 18:00

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

nuander 16.09.2015 02:08

@Kevin Тогда как вы определяете функцию для поддержки ECMAScript 6 (ES6) без eval? Или Крокфорд рекомендует полностью избегать ES6?

Damian Yerrick 18.03.2016 07:42

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

Damian Yerrick 18.03.2016 07:43

@DamianYerrick При обнаружении некоторых функций невозможно не использовать их. Тогда я бы задал вопрос, действительно ли стоит внедрять ES6 в этом сценарии. Если вам нужно выполнить обнаружение функции, чтобы увидеть, можете ли вы ее использовать, это означает, что вы должны учитывать сценарии, в которых вы не можете. На самом деле это означает, что вам нужно написать свой код дважды (один раз в ES5 и один раз в ES6). Я бы просто остался с ES5 или написал код на TypeScript и т.д., чтобы я мог перенести на ES6, когда мне больше не нужно поддерживать 5.

kemiller2002 18.03.2016 16:34

Зачем кому-либо оценивать строку запроса? В настоящее время вам даже не нужно POST, не говоря уже о GET, потому что есть веб-сокеты. И вы всегда можете изолировать iframe или использовать веб-воркер, где между ними передаются только «сообщения» и нет доступа к пространству имен друг друга.

jdmayfield 08.02.2018 08:20

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

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

weaknespase 10.11.2016 20:47

Пока строка не исходит от пользователя или ограничена браузером, вы можете. JavaScript имеет много возможностей для метапрограммирования, используя такие вещи, как изменение прототипов, obj [member], Proxy, json.parse, window, функции декоратора (наречия), где newf = decorator (oldf), функции более высокого порядка, такие как Array.prototype.map (f) , передача аргументов другим функциям, аргументы ключевого слова через {}. Можете ли вы рассказать мне о сценарии использования, в котором вы не можете использовать это вместо eval?

aoeu256 19.07.2019 18:51

Обычно это проблема, только если вы передаете пользовательский ввод eval.

Если вы не на 100% уверены, что оцениваемый код получен из надежного источника (обычно вашего собственного приложения), то это верный способ подвергнуть вашу систему атаке с использованием межсайтовых сценариев.

Только если ваша серверная безопасность - отстой. Безопасность на стороне клиента - полная чушь.

doubleOrt 12.09.2017 02:38

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

Ответ принят как подходящий
  1. Неправильное использование оценка открывает ваши код для инъекционных атак

  2. Отладка может быть сложнее (без номеров строк и т. д.)

  3. Код eval'd выполняется медленнее (нет возможности скомпилировать / кэшировать код eval'd)

Обновлено: Как отмечает @Jeff Walden в комментариях, № 3 сегодня менее верен, чем это было в 2008 году. Однако, хотя может произойти некоторое кеширование скомпилированных скриптов, это будет ограничено только скриптами, которые eval'd повторяются без изменений. Более вероятный сценарий состоит в том, что вы оцениваете сценарии, которые каждый раз подвергались незначительным изменениям и поэтому не могли быть кэшированы. Скажем так, НЕКОТОРЫЙ код eval'd выполняется медленнее.

@JeffWalden, отличный комментарий. Я обновил свой пост, хотя понимаю, что с тех пор, как вы опубликовали, прошел год. Xnzo72, если бы вы немного уточнили свой комментарий (как это сделал Джефф), то я мог бы с вами согласиться. Джефф указал на ключ: «eval одной и той же строки несколько раз может избежать накладных расходов на синтаксический анализ». Как бы то ни было, вы просто ошибаетесь; №3 верен для многих сценариев.

Prestaul 13.02.2012 21:44

@Prestaul: Поскольку предполагаемый злоумышленник может просто использовать любой инструмент разработчика для изменения JavaScript в клиенте, почему вы говорите, что Eval () открывает ваш код для атак путем внедрения? Еще не открыта? (Я, конечно, говорю о клиентском JavaScript)

Eduardo Molteni 24.10.2012 05:52

@EduardoMolteni, нас не волнует (и мы действительно не можем запретить) пользователям запускать js в своих собственных браузерах. Атаки, которые мы пытаемся избежать, - это когда значения, предоставленные пользователем, сохраняются, а затем помещаются в javascript и eval'd. Например, я мог бы установить свое имя пользователя на: badHackerGuy'); doMaliciousThings();, и если вы возьмете мое имя пользователя, объедините его в какой-то скрипт и оцените его в браузерах других людей, тогда я могу запустить любой javascript, который захочу, на их машинах (например, заставить их +1 к моим сообщениям , разместите их данные на моем сервере и т. д.)

Prestaul 25.10.2012 22:12

AFAIK, инструменты разработчика google-chrome и chromium делают отладку eval'ed кода так же, как отладку других файлов js. но вы не можете ставить точки останова.

user405398 09.03.2013 00:38

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

frodeborli 12.03.2014 12:35

@frodeborli, я не согласен с вашим вступительным словом. eval принципиально отличается от вызова функции. Прочтите мой комментарий к EduardoMolteni (2 выше вашего) для объяснения. Инъекционные атаки, в частности, относятся к получению пользовательского ввода и разрешению его выполнения где-нибудь, кроме их собственного браузера. (например, сервер или браузер другого пользователя) Однако я согласен с тем, что eval требуется редко, если вы хорошо спроектируете свои приложения. Этого следует избегать, потому что почти всегда есть лучшее и более безопасное решение.

Prestaul 14.03.2014 19:28

@TamilVendhan Конечно, вы можете ставить точки останова. Вы можете получить доступ к виртуальному файлу, созданному Chrome для вашего расширенного кода, добавив оператор debugger; в исходный код. Это остановит выполнение вашей программы в этой строке. Затем после этого вы можете добавить точки останова отладки, как будто это просто еще один файл JS.

Sid 26.07.2014 02:27

Спасибо. Этот краткий ответ, который я только что сказал, будет именно моим. Я могу использовать eval в моей текущей задаче / контексте. Существует так много непонятных советов просто не использовать его.

ProfK 04.06.2015 16:48

@frodeborli Ваше второе утверждение также неверно. Многие опытные программисты / фреймворки все еще часто используют evil(). Взгляните, например, на SAP OpenUI5.

André Fiedler 10.06.2015 19:27

@ProfK Хорошо подумайте, прежде чем использовать eval()! Существуют более строгие CSP, препятствующие использованию eval(). Возьмем, к примеру, Firefox OS.

André Fiedler 10.06.2015 19:30

@AndreFiedler Ни одно из моих утверждений не является неправильным. Если хотите, можете не согласиться. Любая функциональность может быть реализована на любом полном языке Тьюринга. Лишь в нескольких языках есть eval, поэтому eval НЕ НУЖЕН - это просто удобство. Совершенно другой вопрос, является ли eval вызовом функции или языковой конструкцией.

frodeborli 11.06.2015 21:24

@frodeborli да, это никогда не НУЖНО, но мое заявление касалось experienced programmers often have a better architecture in their code. Не так часто, как вы думали. ;)

André Fiedler 12.06.2015 09:49

@AndreFiedler У опытных программистов может быть плохой код. С этим мы можем согласиться. :) Но группа опытных программистов обычно имеет лучшую архитектуру, чем была у них, когда они были неопытными, вот что я хотел сказать.

frodeborli 13.06.2015 18:29

webpack будет с вами спорить :)

Павел Иванов 26.01.2016 17:48

eval не так уж и плох. Я использую его в своем Epic Random String Generator, и он отлично работает!

SpYk3HH 09.04.2016 06:38

Если вы каждый раз выполняете другой код, компиляция и кеширование не принесут пользы, независимо от того, используете ли вы eval или нет.

Kevin 27.05.2016 20:43

(1) чем это отличается от require / include? Если вам нужно включить внешний код / ​​код пользователя, почему это вообще проблема? (2) современные движки javascript могут сообщить вам точную строку и смещение ошибок внутри оцененного кода, как если бы вы запускали этот код из anonymousScope.js. (3) чем это отличается от любого процесса компиляции? Я бы сказал, что условное создание функции с помощью eval часто бывает быстрее, чем написание функции с условиями в ней или использование глобальных переменных (например, ручное встраивание), когда эти сгенерированные функции вызываются много раз.

Dmitry 02.06.2018 23:43

@Dmitry, я просто обращусь к 1 и 2: большая разница в том, что, если вы используете eval, вы программно генерируете код, и наиболее распространенная причина, по которой люди делают это, - это вводить предоставленную пользователем информацию (или код) в код . Это принципиально небезопасно, так как без нужды открывает ваш код для атак с использованием инъекций. Если вы используете генерацию кода для оптимизации, возможно, это законное использование, но это, безусловно, вариант использования меньшинства.

Prestaul 04.06.2018 19:22

Наиболее частое использование eval - реализовать «требовать» функциональность, не изобретая новый синтаксический анализатор. Также я не уверен, что вы знаете, что такое атаки с использованием инъекций, но на стороне клиента вы не можете избежать инъекций, кроме как локальными объектами функций, а локальные объекты iife не могут быть затронуты ничем, кроме редактора памяти. На стороне сервера вам нужно быть осторожным, кому вы разрешаете выполнять произвольный код, но даже там он все еще используется для реализации требования и в качестве альтернативы оболочки.

Dmitry 04.06.2018 20:46

@ Дмитрий, я думаю, вы в корне неправильно понимаете атаки с использованием инъекций ... Нет никакой угрозы от инъекций, сделанных на стороне клиента пользователем, просматривающим собственный контент. Нас беспокоит XSS, который связан с внедрением вредоносного контента от ДРУГОГО пользователя, предоставляя им доступ к странице, на которой зарегистрирован другой пользователь. Есть способы избежать этого, но если вы используете eval, это полностью зависит от знания и трудолюбие разработчиков. Если вы хотите требовать, просто используйте библиотеку, которая делает это правильно. См .: codereview.stackexchange.com/questions/25901/…

Prestaul 05.06.2018 23:09

@Prestaul eval в xss опасен, но его можно смягчить, скрывая важные данные в локальных переменных внутри функций и проверяя учетные данные перед eval текста, загруженного из чужих доменов. например, вместо eval кода вы можете json проанализировать запрос на eval и проверить учетные данные объектов перед eval его свойства кода. Тем не менее, я не могу представить, что нужно оценивать xss.

Dmitry 06.06.2018 02:27

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

На ум приходят два момента:

  1. Безопасность (но если вы сами генерируете строку для оценки, это может быть не проблема)

  2. Производительность: пока код, который нужно выполнить, неизвестен, его нельзя оптимизировать. (про javascript и производительность, обязательно Презентация Стива Егге)

Почему безопасность является проблемой, если клиент в любом случае может делать с нашим кодом все, что хочет? Грязная обезьяна ?

Paul Brewczynski 10.03.2013 20:01

@PaulBrewczynski, проблема безопасности возникает, когда пользователь A сохраняет свою часть кода для evaluated, а затем этот небольшой фрагмент кода запускается в браузере пользователя B.

Felipe Pereira 03.12.2014 17:33

Если вы не разрешите eval () динамический контент (через cgi или input), он будет таким же безопасным и надежным, как и любой другой JavaScript на вашей странице.

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

Periata Breatta 26.10.2016 19:22

Просто, например, для анализа возвращаемого значения (например, JSON-строк, определенных сервером строк и т. д.), Полученного в результате вызова Ajax.

Thevs 27.10.2016 15:34

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

Periata Breatta 29.10.2016 16:10

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

За 3+ года, прошедшие с тех пор, как я ответил на этот вопрос, мое понимание происходящего, скажем так, углубилось. На самом деле происходит создание нового контекста выполнения. См. dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts

Andrew Hedges 26.01.2012 07:46

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

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

Это значительно снижает уровень вашей уверенности в безопасности.

Это не обязательно так плохо, если вы знаете, в каком контексте вы его используете.

Если ваше приложение использует eval() для создания объекта из некоторого JSON, который вернулся из XMLHttpRequest на ваш собственный сайт, созданный вашим доверенным серверным кодом, это, вероятно, не проблема.

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

Разве использование eval не медленнее, чем просто парсинг JSON?

Brendan Long 05.04.2011 04:24

@Qix - запуск этого теста в моем браузере (Chrome 53) показывает, что оценка несколько быстрее, чем разбирать.

Periata Breatta 26.10.2016 19:26

@PeriataBreatta А, странно. Интересно, почему. В то время я прокомментировал, что это не так. Тем не менее, Chrome нередко получает странное повышение производительности в определенных областях среды выполнения от версии к версии.

Qix - MONICA WAS MISTREATED 26.10.2016 19:36

Здесь небольшая старая ветка, но из того, что я прочитал - не утверждая, что я сам проследил это - JSON.parse на самом деле eval вводит его на заключительном этапе. Так что с точки зрения эффективности требуется больше работы / времени. Но с точки зрения безопасности, почему бы просто не проанализировать? eval - отличный инструмент. Используйте его для вещей, у которых нет другого пути. Чтобы передавать функции через JSON, есть способ сделать это без eval. Этот второй параметр в JSON.stringify позволяет вам запустить обратный вызов, который вы можете проверить с помощью typeof, если это функция. Затем получите функцию .toString (). Если поискать, есть несколько хороших статей по этому поводу.

jdmayfield 08.02.2018 08:07

eval не всегда злой. Бывают моменты, когда это совершенно уместно.

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

Чтобы дать слишком типичный пример, чтобы установить цвет элемента с идентификатором, хранящимся в переменной 'potato':

eval('document.' + potato + '.style.color = "red"');

Если бы авторы приведенного выше кода имели представление об основах работы объектов JavaScript, они бы поняли, что вместо буквальных имен точек можно использовать квадратные скобки, устраняя необходимость в eval:

document[potato].style.color = 'red';

... который намного легче читать, а также в нем меньше ошибок.

(Но тогда кто-то, кто / действительно / знал, что они делают, сказал бы:

document.getElementById(potato).style.color = 'red';

что более надежно, чем старый хитрый трюк с доступом к элементам DOM прямо из объекта документа.)

Хм, думаю, мне повезло, когда я впервые изучал JavaScript. Я всегда использовал document.getElementById для доступа к DOM; по иронии судьбы, в то время я сделал это только потому, что понятия не имел, как объекты работают в JavaScript ;-)

Mike Spross 15.03.2009 09:45

согласны. Иногда eval в порядке, например для ответов JSON от веб-сервисов

schoetbi 03.01.2011 18:17

@schoetbi: Разве вы не должны использовать JSON.parse() вместо eval() для JSON?

nyuszika7h 11.01.2011 00:46

@ Nyuszika7H: когда сможешь, конечно. Увы, есть еще несколько браузеров, в которых его нет.

bobince 11.01.2011 03:53

@bobince code.google.com/p/json-sans-eval работает во всех браузерах, как и github.com/douglascrockford/JSON-js. Json2.js Дуга Крокфорда действительно использует eval внутри, но с проверками. Кроме того, он совместим со встроенной поддержкой JSON в браузере.

Martijn 01.02.2011 13:13

Конечно, вы можете использовать библиотеки, если хотите. Но все браузеры должны будут загрузить код библиотеки, даже если у них есть встроенная поддержка, поэтому они никогда не будут его использовать. В случаях, когда я уверен, что JSON будет безопасным и действительным как литерал JS, а также как JSON, я бы предпочел сэкономить лишний объем и пухлость для eval.

bobince 05.02.2011 14:38

@bobince Есть что-то, что называется функцией обнаружения и полифиллами, для обработки недостающих библиотек JSON и других вещей (см. modernizr.com)

MauganRa 22.11.2012 20:04

«eval - не всегда зло». Не так ли? Я не знаю ни одного случая, когда eval был бы лучшим вариантом. FWIW вы можете достичь большей части той же функциональности, используя конструктор Function (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…), что немного менее злобно.

David Knipe 07.06.2019 23:25

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

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

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

Однако по всем причинам, упомянутым выше, вы не должны использовать его для своего собственного кода, где у вас есть полный контроль - это просто не обязательно, и лучше отнести его к полке «хитрых хаков JavaScript».

Просто обновите приведенный выше код .. --hi there! - необходимо заключить в кавычки, так как это строка. eval ('al' + 'er' + 't (' + '«привет!»' + ')');

Mahesh 20.05.2014 09:23

[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()

Konrad Borowski 21.09.2014 15:57

Ура, были сайты социальных сетей, которые ограничивали alert (), но разрешали eval () ?!

joshden 06.04.2016 17:48

Если вы хотите, чтобы пользователь ввел некоторые логические функции и оценил ИЛИ, тогда функция eval в JavaScript идеально подойдет. Я могу принять две струны и eval(uate) string1 === string2 и т. д.

Вы также можете использовать Function () {}, но будьте осторожны при использовании их на сервере, если вы не хотите, чтобы пользователи перехватили ваш сервер, ха-ха-ха.

aoeu256 19.07.2019 18:45

Наряду с остальными ответами я не думаю, что операторы eval могут иметь расширенную минимизацию.

Я знаю, что это старое обсуждение, но мне очень нравится подход это от Google, и я хотел поделиться этим чувством с другими;)

Другое дело, что чем лучше Ты получаешь, тем больше пытаешься понять и, наконец, просто не веришь, что что-то хорошо или плохо только потому, что кто-то так сказал :) Это очень вдохновляющий видео, который помог мне больше думать самостоятельно :) ХОРОШИЕ ПРАКТИКИ - это хорошо, но не используйте их бездумно :)

Да. Я нашел, по крайней мере, пока в Chrome, вариант использования, который кажется более эффективным. Запустите RAF, который вычисляет строку в заданной переменной на каждой итерации. Используйте setInterval для установки в этой строке только графически ориентированных вещей, таких как установка преобразований и т. д. Я пробовал много других подходов, таких как перебор функций в массиве или использование переменной для установки преобразований только для изменяемых элементов, но пока это кажется наиболее эффективным. Когда дело доходит до анимации, самый верный тест - это ваши глаза.

jdmayfield 08.02.2018 08:32

Это одна из хороших статей о eval и о том, что это не зло: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstand/

I’m not saying you should go run out and start using eval() everywhere. In fact, there are very few good use cases for running eval() at all. There are definitely concerns with code clarity, debugability, and certainly performance that should not be overlooked. But you shouldn’t be afraid to use it when you have a case where eval() makes sense. Try not using it first, but don’t let anyone scare you into thinking your code is more fragile or less secure when eval() is used appropriately.

eval () очень мощный и может использоваться для выполнения оператора JS или оценки выражения. Но вопрос не в использовании eval (), а просто скажем, как на строку, которую вы запускаете с eval (), влияет злоумышленник. В конце у вас будет запущен вредоносный код. С властью приходит большая ответственность. Так что используйте его с умом, если вы его используете. Это не имеет большого отношения к функции eval (), но в этой статье есть довольно хорошая информация: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Если вы ищете основы eval (), посмотрите здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

Я не буду пытаться опровергнуть что-либо сказанное ранее, но я предложу такое использование 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);

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

это можно сделать с помощью namespaceToTest[namespaceParts[i]], здесь нет необходимости в eval, поэтому if (typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {}; - единственное отличие от else namespaceToTest = namespaceToTest[namespaceParts[i]];.

user2144406 14.04.2016 17:08

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

Но если движок находит 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

Ни один движок javascript не может найти и оценить в коде со 100% гарантией. Поэтому он должен быть к этому готов в любой момент.

Jack Giffin 10.05.2018 05:37

Это не всегда плохая идея. Возьмем, к примеру, генерацию кода. Недавно я написал библиотеку под названием Гипербары, которая устраняет разрыв между виртуальный дом и рули. Он делает это путем анализа шаблона ручек и преобразования его в гипертекст, который впоследствии используется 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() не является проблемой в такой ситуации, потому что вам нужно только один раз интерпретировать сгенерированную строку, а затем многократно повторно использовать выходные данные исполняемого файла.

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

Если вы заметили использование eval () в своем коде, вспомните мантру «eval () - зло».

Этот Функция принимает произвольную строку и выполняет ее как код JavaScript. Когда код в вопрос известен заранее (не определяется во время выполнения), нет причин использовать eval (). Если код создается динамически во время выполнения, часто есть лучший способ достичь цели без eval (). Например, просто используя обозначение квадратных скобок для доступ к динамическим свойствам стал лучше и проще:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Использование eval() также имеет последствия для безопасности, поскольку вы можете выполнять код (для пример поступает из сети), в которую были внесены изменения. Это распространенный антипаттерн при работе с ответом JSON на запрос Ajax. В тех случаях лучше использовать встроенные методы браузера для анализа ответа JSON, чтобы уверен, что это безопасно и правильно. Для браузеров, которые не поддерживают JSON.parse(), вы можете используйте библиотеку с JSON.org.

Также важно помнить, что передача строк в setInterval(), setTimeout(), а конструктор Function() по большей части аналогичен использованию eval() и, следовательно, необходимо избегать.

За кулисами JavaScript все еще должен оценивать и выполнять строка, которую вы передаете как программный код:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

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

Есть небольшой потенциал выгода, потому что код, оцениваемый в new Function (), будет выполняться в локальной функции область видимости, поэтому любые переменные, определенные с помощью var в оцениваемом коде, не станут globals автоматически.

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

Не могли бы вы подсказать, как я могу оценить имя динамической переменной, локальное для функции, без eval? Функции Eval (и подобные) являются последним средством на большинстве языков, которые их содержат, но иногда это необходимо. В случае получения имени динамической переменной какое решение является более безопасным? В любом случае, сам javascript не обеспечивает реальной безопасности (серверная сторона, очевидно, является основной защитой). Если вам интересно, вот мой вариант использования eval, который я бы хотел изменить: stackoverflow.com/a/48294208

Regular Jo 17.01.2018 08:49

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

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

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

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

есть не только консоль разработчика, вы также можете ввести javascript: code в адресную строку, чтобы создать собственную консоль разработчика на странице, если ее нет, как в старых браузерах IE и мобильных устройствах.

Dmitry 02.06.2018 23:56

Вывоз мусора

Сборка мусора браузеров не знает, можно ли удалить код, который eval'ed, из памяти, поэтому он просто хранит его, пока страница не будет перезагружена. Не так уж и плохо, если ваши пользователи будут на вашей странице только в ближайшее время, но это может стать проблемой для веб-приложений.

Вот сценарий для демонстрации проблемы

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

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

Другие вопросы по теме