Функция eval - мощный и простой способ динамически генерировать код, так каковы же предостережения?
Как указано в moduscreate.com/javascript-performance-tips-tricks - (new Function (str)) () более производительна, чем eval (str). Всего мои 2 цента :)
очевидно, новая функция (a) на 67% медленнее, чем eval (a) на chrome
для меня новые функции (а) на 80% медленнее последней версии Chrome на osx
Я добавил статическую функцию, просто чтобы сравнить производительность. jsperf.com/eval-vs-new-function/2
те же предостережения, что и include и require в PHP. eval также можно назвать "include_from_string" или "runtime_compile". Мало того, что это не зло, но я уверен, что это одна из фундаментальных причин создания сценариев - гораздо проще создать сценарий, который приближается к объекту, и начать его использовать / изменять без перекомпиляции, чем перекомпилировать DLL каждый раз. раз вам нужны перемены. С точки зрения высокого уровня Eval - это то же самое, что компилировать файл c в DLL, затем вызывать его «точку входа» и связываться с его »символом состояния (или заставить точку входа вернуть объект состояния).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я считаю, что это потому, что он может выполнять любую функцию JavaScript из строки. Его использование упрощает внедрение мошеннического кода в приложение.
Какая же тогда альтернатива?
На самом деле альтернатива - просто написать код, который этого не требует. Крокфорд подробно рассказывает об этом, и, если вам нужно его использовать, он в значительной степени говорит, что это недостаток дизайна программы и его необходимо переделать. По правде говоря, я тоже с ним согласен. JS, несмотря на все его недостатки, действительно гибок и позволяет сделать его гибким.
но когда вы получите ответ от сервера с помощью AJAX, вы получите текст ответа xmlHttp.responseText, и вам нужно будет использовать eval для его выполнения.
Неправда, у большинства фреймворков есть метод анализа JSON, и если вы не используете фреймворк, вы можете использовать JSON.parse (). Большинство браузеров поддерживают его, и если вы действительно в затруднительном положении, вы можете довольно легко написать парсер для JSON.
Я не верю этому аргументу, потому что уже сейчас несложно внедрить мошеннический код в приложение Javascript. У нас есть консоли браузера, расширения сценариев и т. д. Каждый фрагмент кода, отправляемый клиенту, не является обязательным для выполнения клиентом.
Дело в том, что мне проще внедрить код в ваш браузер. Допустим, вы используете eval в строке запроса. Если я обманом заставлю вас щелкнуть ссылку, ведущую на этот сайт с прикрепленной строкой запроса, то теперь я выполнил свой код на вашем компьютере с полным разрешением браузера. Я хочу записывать в журнал все, что вы вводите на этом сайте, и отправлять мне? Готово, и меня не остановить, потому что при выполнении eval браузер дает ему наивысшие полномочия.
Я использую его для обработки динамических формул, когда формула отправляется с сервера. Здесь нет угрозы безопасности, и единственной альтернативой было бы написать большую функцию JavaScript для деконструкции формул.
@Kevin Тогда как вы определяете функцию для поддержки ECMAScript 6 (ES6) без eval? Или Крокфорд рекомендует полностью избегать ES6?
@nuander Затем выполните большую функцию как отдельный файл .js и включите его, добавив в документ элемент сценария.
@DamianYerrick При обнаружении некоторых функций невозможно не использовать их. Тогда я бы задал вопрос, действительно ли стоит внедрять ES6 в этом сценарии. Если вам нужно выполнить обнаружение функции, чтобы увидеть, можете ли вы ее использовать, это означает, что вы должны учитывать сценарии, в которых вы не можете. На самом деле это означает, что вам нужно написать свой код дважды (один раз в ES5 и один раз в ES6). Я бы просто остался с ES5 или написал код на TypeScript и т.д., чтобы я мог перенести на ES6, когда мне больше не нужно поддерживать 5.
Зачем кому-либо оценивать строку запроса? В настоящее время вам даже не нужно POST, не говоря уже о GET, потому что есть веб-сокеты. И вы всегда можете изолировать iframe или использовать веб-воркер, где между ними передаются только «сообщения» и нет доступа к пространству имен друг друга.
В основном, его намного сложнее поддерживать и отлаживать. Это как goto. Вы можете использовать его, но это усложняет поиск проблем и усложняет задачу людям, которым, возможно, потребуется внести изменения позже.
Eval можно использовать для замены отсутствующих функций метапрограммирования, например шаблонов. Мне больше нравится компактный генератор, чем бесконечный список функций за функциями.
Пока строка не исходит от пользователя или ограничена браузером, вы можете. JavaScript имеет много возможностей для метапрограммирования, используя такие вещи, как изменение прототипов, obj [member], Proxy, json.parse, window, функции декоратора (наречия), где newf = decorator (oldf), функции более высокого порядка, такие как Array.prototype.map (f) , передача аргументов другим функциям, аргументы ключевого слова через {}. Можете ли вы рассказать мне о сценарии использования, в котором вы не можете использовать это вместо eval?
Обычно это проблема, только если вы передаете пользовательский ввод eval.
Если вы не на 100% уверены, что оцениваемый код получен из надежного источника (обычно вашего собственного приложения), то это верный способ подвергнуть вашу систему атаке с использованием межсайтовых сценариев.
Только если ваша серверная безопасность - отстой. Безопасность на стороне клиента - полная чушь.
Помимо возможных проблем с безопасностью, если вы выполняете код, отправленный пользователем, в большинстве случаев есть лучший способ, который не включает повторный синтаксический анализ кода при каждом его выполнении. Анонимные функции или свойства объекта могут заменить большинство применений eval и намного безопаснее и быстрее.
Неправильное использование оценка открывает ваши код для инъекционных атак
Отладка может быть сложнее (без номеров строк и т. д.)
Код eval'd выполняется медленнее (нет возможности скомпилировать / кэшировать код eval'd)
Обновлено: Как отмечает @Jeff Walden в комментариях, № 3 сегодня менее верен, чем это было в 2008 году. Однако, хотя может произойти некоторое кеширование скомпилированных скриптов, это будет ограничено только скриптами, которые eval'd повторяются без изменений. Более вероятный сценарий состоит в том, что вы оцениваете сценарии, которые каждый раз подвергались незначительным изменениям и поэтому не могли быть кэшированы. Скажем так, НЕКОТОРЫЙ код eval'd выполняется медленнее.
@JeffWalden, отличный комментарий. Я обновил свой пост, хотя понимаю, что с тех пор, как вы опубликовали, прошел год. Xnzo72, если бы вы немного уточнили свой комментарий (как это сделал Джефф), то я мог бы с вами согласиться. Джефф указал на ключ: «eval одной и той же строки несколько раз может избежать накладных расходов на синтаксический анализ». Как бы то ни было, вы просто ошибаетесь; №3 верен для многих сценариев.
@Prestaul: Поскольку предполагаемый злоумышленник может просто использовать любой инструмент разработчика для изменения JavaScript в клиенте, почему вы говорите, что Eval () открывает ваш код для атак путем внедрения? Еще не открыта? (Я, конечно, говорю о клиентском JavaScript)
@EduardoMolteni, нас не волнует (и мы действительно не можем запретить) пользователям запускать js в своих собственных браузерах. Атаки, которые мы пытаемся избежать, - это когда значения, предоставленные пользователем, сохраняются, а затем помещаются в javascript и eval'd. Например, я мог бы установить свое имя пользователя на: badHackerGuy'); doMaliciousThings();, и если вы возьмете мое имя пользователя, объедините его в какой-то скрипт и оцените его в браузерах других людей, тогда я могу запустить любой javascript, который захочу, на их машинах (например, заставить их +1 к моим сообщениям , разместите их данные на моем сервере и т. д.)
AFAIK, инструменты разработчика google-chrome и chromium делают отладку eval'ed кода так же, как отладку других файлов js. но вы не можете ставить точки останова.
В общем, # 1 верно для довольно многих, если не для большинства вызовов функций. Опытные программисты не должны выделять и избегать eval () только потому, что неопытные программисты злоупотребляют ею. Однако опытные программисты часто имеют лучшую архитектуру в своем коде, а eval () будет редко требоваться или даже думать о нем из-за этой лучшей архитектуры.
@frodeborli, я не согласен с вашим вступительным словом. eval принципиально отличается от вызова функции. Прочтите мой комментарий к EduardoMolteni (2 выше вашего) для объяснения. Инъекционные атаки, в частности, относятся к получению пользовательского ввода и разрешению его выполнения где-нибудь, кроме их собственного браузера. (например, сервер или браузер другого пользователя) Однако я согласен с тем, что eval требуется редко, если вы хорошо спроектируете свои приложения. Этого следует избегать, потому что почти всегда есть лучшее и более безопасное решение.
@TamilVendhan Конечно, вы можете ставить точки останова. Вы можете получить доступ к виртуальному файлу, созданному Chrome для вашего расширенного кода, добавив оператор debugger; в исходный код. Это остановит выполнение вашей программы в этой строке. Затем после этого вы можете добавить точки останова отладки, как будто это просто еще один файл JS.
Спасибо. Этот краткий ответ, который я только что сказал, будет именно моим. Я могу использовать eval в моей текущей задаче / контексте. Существует так много непонятных советов просто не использовать его.
@frodeborli Ваше второе утверждение также неверно. Многие опытные программисты / фреймворки все еще часто используют evil(). Взгляните, например, на SAP OpenUI5.
@ProfK Хорошо подумайте, прежде чем использовать eval()! Существуют более строгие CSP, препятствующие использованию eval(). Возьмем, к примеру, Firefox OS.
@AndreFiedler Ни одно из моих утверждений не является неправильным. Если хотите, можете не согласиться. Любая функциональность может быть реализована на любом полном языке Тьюринга. Лишь в нескольких языках есть eval, поэтому eval НЕ НУЖЕН - это просто удобство. Совершенно другой вопрос, является ли eval вызовом функции или языковой конструкцией.
@frodeborli да, это никогда не НУЖНО, но мое заявление касалось experienced programmers often have a better architecture in their code. Не так часто, как вы думали. ;)
@AndreFiedler У опытных программистов может быть плохой код. С этим мы можем согласиться. :) Но группа опытных программистов обычно имеет лучшую архитектуру, чем была у них, когда они были неопытными, вот что я хотел сказать.
webpack будет с вами спорить :)
eval не так уж и плох. Я использую его в своем Epic Random String Generator, и он отлично работает!
Если вы каждый раз выполняете другой код, компиляция и кеширование не принесут пользы, независимо от того, используете ли вы eval или нет.
(1) чем это отличается от require / include? Если вам нужно включить внешний код / код пользователя, почему это вообще проблема? (2) современные движки javascript могут сообщить вам точную строку и смещение ошибок внутри оцененного кода, как если бы вы запускали этот код из anonymousScope.js. (3) чем это отличается от любого процесса компиляции? Я бы сказал, что условное создание функции с помощью eval часто бывает быстрее, чем написание функции с условиями в ней или использование глобальных переменных (например, ручное встраивание), когда эти сгенерированные функции вызываются много раз.
@Dmitry, я просто обращусь к 1 и 2: большая разница в том, что, если вы используете eval, вы программно генерируете код, и наиболее распространенная причина, по которой люди делают это, - это вводить предоставленную пользователем информацию (или код) в код . Это принципиально небезопасно, так как без нужды открывает ваш код для атак с использованием инъекций. Если вы используете генерацию кода для оптимизации, возможно, это законное использование, но это, безусловно, вариант использования меньшинства.
Наиболее частое использование eval - реализовать «требовать» функциональность, не изобретая новый синтаксический анализатор. Также я не уверен, что вы знаете, что такое атаки с использованием инъекций, но на стороне клиента вы не можете избежать инъекций, кроме как локальными объектами функций, а локальные объекты iife не могут быть затронуты ничем, кроме редактора памяти. На стороне сервера вам нужно быть осторожным, кому вы разрешаете выполнять произвольный код, но даже там он все еще используется для реализации требования и в качестве альтернативы оболочки.
@ Дмитрий, я думаю, вы в корне неправильно понимаете атаки с использованием инъекций ... Нет никакой угрозы от инъекций, сделанных на стороне клиента пользователем, просматривающим собственный контент. Нас беспокоит XSS, который связан с внедрением вредоносного контента от ДРУГОГО пользователя, предоставляя им доступ к странице, на которой зарегистрирован другой пользователь. Есть способы избежать этого, но если вы используете eval, это полностью зависит от знания и трудолюбие разработчиков. Если вы хотите требовать, просто используйте библиотеку, которая делает это правильно. См .: codereview.stackexchange.com/questions/25901/…
@Prestaul eval в xss опасен, но его можно смягчить, скрывая важные данные в локальных переменных внутри функций и проверяя учетные данные перед eval текста, загруженного из чужих доменов. например, вместо eval кода вы можете json проанализировать запрос на eval и проверить учетные данные объектов перед eval его свойства кода. Тем не менее, я не могу представить, что нужно оценивать xss.
Это может стать более серьезной проблемой, поскольку следующее поколение браузеров выходит с некоторой разновидностью компилятора JavaScript. Код, выполняемый через Eval, может не работать так же хорошо, как остальная часть вашего JavaScript в этих новых браузерах. Кто-то должен профилировать.
На ум приходят два момента:
Безопасность (но если вы сами генерируете строку для оценки, это может быть не проблема)
Производительность: пока код, который нужно выполнить, неизвестен, его нельзя оптимизировать. (про javascript и производительность, обязательно Презентация Стива Егге)
Почему безопасность является проблемой, если клиент в любом случае может делать с нашим кодом все, что хочет? Грязная обезьяна ?
@PaulBrewczynski, проблема безопасности возникает, когда пользователь A сохраняет свою часть кода для evaluated, а затем этот небольшой фрагмент кода запускается в браузере пользователя B.
Если вы не разрешите eval () динамический контент (через cgi или input), он будет таким же безопасным и надежным, как и любой другой JavaScript на вашей странице.
Хотя это правда - если ваш контент не динамический, зачем вообще использовать eval для него? Вместо этого вы можете просто поместить код в функцию и вызвать ее!
Просто, например, для анализа возвращаемого значения (например, JSON-строк, определенных сервером строк и т. д.), Полученного в результате вызова Ajax.
А ну понятно. Я бы назвал их динамическими, потому что клиент не знает заранее, что это такое, но теперь я понимаю, что вы имеете в виду.
Передача пользовательского ввода в eval () представляет собой угрозу безопасности, но также каждый вызов eval () создает новый экземпляр интерпретатора JavaScript. Это может быть пожирателем ресурсов.
За 3+ года, прошедшие с тех пор, как я ответил на этот вопрос, мое понимание происходящего, скажем так, углубилось. На самом деле происходит создание нового контекста выполнения. См. dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Это возможный риск для безопасности, он имеет другую область выполнения и довольно неэффективен, поскольку создает совершенно новую среду сценариев для выполнения кода. См. Дополнительную информацию здесь: оценка.
Тем не менее, это довольно полезно, и при модерации может добавить много полезных функций.
Это значительно снижает уровень вашей уверенности в безопасности.
Это не обязательно так плохо, если вы знаете, в каком контексте вы его используете.
Если ваше приложение использует eval() для создания объекта из некоторого JSON, который вернулся из XMLHttpRequest на ваш собственный сайт, созданный вашим доверенным серверным кодом, это, вероятно, не проблема.
Недоверенный клиентский код JavaScript в любом случае не может этого сделать. Если вещь, на которой вы запускаете eval(), поступила из разумного источника, все в порядке.
Разве использование eval не медленнее, чем просто парсинг JSON?
@Qix - запуск этого теста в моем браузере (Chrome 53) показывает, что оценка несколько быстрее, чем разбирать.
@PeriataBreatta А, странно. Интересно, почему. В то время я прокомментировал, что это не так. Тем не менее, Chrome нередко получает странное повышение производительности в определенных областях среды выполнения от версии к версии.
Здесь небольшая старая ветка, но из того, что я прочитал - не утверждая, что я сам проследил это - JSON.parse на самом деле eval вводит его на заключительном этапе. Так что с точки зрения эффективности требуется больше работы / времени. Но с точки зрения безопасности, почему бы просто не проанализировать? eval - отличный инструмент. Используйте его для вещей, у которых нет другого пути. Чтобы передавать функции через JSON, есть способ сделать это без eval. Этот второй параметр в JSON.stringify позволяет вам запустить обратный вызов, который вы можете проверить с помощью typeof, если это функция. Затем получите функцию .toString (). Если поискать, есть несколько хороших статей по этому поводу.
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 ;-)
согласны. Иногда eval в порядке, например для ответов JSON от веб-сервисов
@schoetbi: Разве вы не должны использовать JSON.parse() вместо eval() для JSON?
@ Nyuszika7H: когда сможешь, конечно. Увы, есть еще несколько браузеров, в которых его нет.
@bobince code.google.com/p/json-sans-eval работает во всех браузерах, как и github.com/douglascrockford/JSON-js. Json2.js Дуга Крокфорда действительно использует eval внутри, но с проверками. Кроме того, он совместим со встроенной поддержкой JSON в браузере.
Конечно, вы можете использовать библиотеки, если хотите. Но все браузеры должны будут загрузить код библиотеки, даже если у них есть встроенная поддержка, поэтому они никогда не будут его использовать. В случаях, когда я уверен, что JSON будет безопасным и действительным как литерал JS, а также как JSON, я бы предпочел сэкономить лишний объем и пухлость для eval.
@bobince Есть что-то, что называется функцией обнаружения и полифиллами, для обработки недостающих библиотек JSON и других вещей (см. modernizr.com)
«eval - не всегда зло». Не так ли? Я не знаю ни одного случая, когда eval был бы лучшим вариантом. FWIW вы можете достичь большей части той же функциональности, используя конструктор Function (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…), что немного менее злобно.
Следует иметь в виду, что вы часто можете использовать eval () для выполнения кода в другой ограниченной среде - сайты социальных сетей, которые блокируют определенные функции JavaScript, иногда можно обмануть, разбив их в блоке eval -
eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');
Так что, если вы хотите запустить какой-то код JavaScript, где это было бы недопустимо (Мое пространство, я смотрю на вас ...), то eval () может быть полезным трюком.
Однако по всем причинам, упомянутым выше, вы не должны использовать его для своего собственного кода, где у вас есть полный контроль - это просто не обязательно, и лучше отнести его к полке «хитрых хаков JavaScript».
Просто обновите приведенный выше код .. --hi there! - необходимо заключить в кавычки, так как это строка. eval ('al' + 'er' + 't (' + '«привет!»' + ')');
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Ура, были сайты социальных сетей, которые ограничивали alert (), но разрешали eval () ?!
Если вы хотите, чтобы пользователь ввел некоторые логические функции и оценил ИЛИ, тогда функция eval в JavaScript идеально подойдет. Я могу принять две струны и eval(uate) string1 === string2 и т. д.
Вы также можете использовать Function () {}, но будьте осторожны при использовании их на сервере, если вы не хотите, чтобы пользователи перехватили ваш сервер, ха-ха-ха.
Наряду с остальными ответами я не думаю, что операторы eval могут иметь расширенную минимизацию.
Я знаю, что это старое обсуждение, но мне очень нравится подход это от Google, и я хотел поделиться этим чувством с другими;)
Другое дело, что чем лучше Ты получаешь, тем больше пытаешься понять и, наконец, просто не веришь, что что-то хорошо или плохо только потому, что кто-то так сказал :) Это очень вдохновляющий видео, который помог мне больше думать самостоятельно :) ХОРОШИЕ ПРАКТИКИ - это хорошо, но не используйте их бездумно :)
Да. Я нашел, по крайней мере, пока в Chrome, вариант использования, который кажется более эффективным. Запустите RAF, который вычисляет строку в заданной переменной на каждой итерации. Используйте setInterval для установки в этой строке только графически ориентированных вещей, таких как установка преобразований и т. д. Я пробовал много других подходов, таких как перебор функций в массиве или использование переменной для установки преобразований только для изменяемых элементов, но пока это кажется наиболее эффективным. Когда дело доходит до анимации, самый верный тест - это ваши глаза.
Это одна из хороших статей о 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]];.
В движке 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% гарантией. Поэтому он должен быть к этому готов в любой момент.
Это не всегда плохая идея. Возьмем, к примеру, генерацию кода. Недавно я написал библиотеку под названием Гипербары, которая устраняет разрыв между виртуальный дом и рули. Он делает это путем анализа шаблона ручек и преобразования его в гипертекст, который впоследствии используется 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
Я бы даже сказал, что на самом деле не имеет значения, используете ли вы eval() в javascript, который запускается в браузерах. * (Предостережение)
Все современные браузеры имеют консоль разработчика, где вы в любом случае можете выполнять произвольный javascript, и любой полуумный разработчик может посмотреть на ваш исходный код JS и поместить любые его части в консоль разработчика, чтобы делать то, что они хотят.
* Пока конечные точки вашего сервера имеют правильную проверку и дезинфекцию значений, предоставленных пользователем, не имеет значения, что анализируется и оценивается в javascript на стороне клиента.
Однако, если вы спросите, подходит ли использование eval() в PHP, ответ будет НЕТ, если вы не белый список любых значений, которые могут быть переданы в ваш оператор eval.
есть не только консоль разработчика, вы также можете ввести javascript: code в адресную строку, чтобы создать собственную консоль разработчика на странице, если ее нет, как в старых браузерах IE и мобильных устройствах.
Вывоз мусора
Сборка мусора браузеров не знает, можно ли удалить код, который eval'ed, из памяти, поэтому он просто хранит его, пока страница не будет перезагружена. Не так уж и плохо, если ваши пользователи будут на вашей странице только в ближайшее время, но это может стать проблемой для веб-приложений.
Вот сценарий для демонстрации проблемы
https://jsfiddle.net/CynderRnAsh/qux1osnw/
document.getElementById("evalLeak").onclick = (e) => {
for(let x = 0; x < 100; x++) {
eval(x.toString());
}
};
Что-то столь же простое, как приведенный выше код, заставляет хранить небольшой объем памяти до тех пор, пока приложение не умрет. Это хуже, когда исключенный сценарий является гигантской функцией и вызывается с интервалом.
Не будь eval () Саймоном Уиллисоном - 24ways.org/2005/dont-be-eval