ты не знаешь

внешний интерфейс JavaScript V8 MVVM

предисловие

eval() — очень полезная функция в JavaScript, которую можно выполнять динамически из строки кода. Тем не менее, различные стандарты кодирования и лучшие практики сильно сопротивляются eval, и почти отправляют eval в камеру смертников.Дуглас Крокфорд, Дэниел, также считает eval отбросами JavaScript в своей книге «Сущность языка JavaScript». Эта статья заставит всех заново понять эту функцию, узнать, почему она не используется и почему ее необходимо использовать.

что такое оценка

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

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

При прямом вызове eval запускается в рамках своей вызывающей функции;

var context = 'outside';
(function(){
  var context = 'inside';
  return eval('context');
})();

// return 'inside'

При косвенном вызове eval работает в глобальной области видимости.

var context = 'outside';
(function(){
  var context = 'inside';
  geval = eval;
  return geval('context');
  
  // 下面两种也属于间接调用
  // return eval.call(null, 'context');
  // return (1, eval)('context');
})();

// return 'outside'

Таким образом, при косвенном вызове eval ничего не изменяет в области действия вызывающей функции. Интерпретатор JS имеет два режима: быстрый путь и медленный путь, При прямом вызове eval интерпретатор находится в медленном пути. Поскольку в настоящее время область действия не поддается контролю, необходимо отслеживать всю область действия, некоторые оптимизации компиляции версии 8 не могут быть применены, и соответствующая эффективность компиляции будет ниже, чем у быстрого пути.

почему бы не использовать eval

Причины Boycott Eval в основном следующие причины:

  1. снизить производительность. Конкретные причины были упомянуты выше, а в некоторых статьях в Интернете даже говорится, что eval() снизит производительность в 10 раз.
  2. безопасный вопрос. Из-за своих динамических характеристик выполнения он дает слишком много мощности оцениваемой строке, поэтому все беспокоятся, что это может привести к XSS и другим атакам.
  3. Сложность отладки. eval подобен черному ящику, код, который он выполняет, трудно отлаживать с помощью точек останова.

По всем этим причинам многие говорят, что eval — это зло. Кроме того, у eval есть трудные собратья, такие как new Function, setTimeout, setInterval. У них также есть возможность выполнить строку кода.Существенная причина в том, что JS дает этому методу слишком много полномочий, и его трудно контролировать новичку., легко писать задачи без хорошего понимания eval . Это немного похоже на оператор goto в языке C, который также является моделью блокировки из-за слишком большого количества разрешений.

неправильно понятый

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

  1. О том, что eval снижает производительность в 10 раз, выступление инженера Mozila«Знай свой движок — как сделать свой JavaScript быстрым».
    Это доклад, опубликованный в 2011 году, и по сей день движок JS выполняет различные оптимизации. Давайте проверим фактическую производительность eval в текущем движке JS. По-прежнему используйте приведенное выше изображение в качестве тестового примера, тестовая среда — узел v8.11.1, а значение N установлено на 10000.
    image.png
    По данным Benchmark, при N = 10000 скорость выполнения функции с eval более чем в 3 раза ниже, чем без eval. Установка значения N равным 1000000 снижает производительность eval в 8 раз.
    image.png

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

  1. Что касается того, что eval может привести к XSS-атакам, то проблема не в eval, а в источнике данных. Если источник данных по своей сути ненадежен, XSS может возникнуть, даже если вы не используете eval.
  2. Что касается третьего пункта, код eval действительно более проблематичен для отладки, но не совсем невозможен. Вы можете назвать этот код, добавив строку «//@sourceURL=name» в конец кода, созданного eval (браузер специально обрабатывает эту специальную форму комментариев), поэтому он появится на панели «Источники», а затем просто Вы можете установить точки останова для отладки.

Настоящее предупреждение об аромате

Хотя все говорят не использовать его, eval действительно благоухает при использовании.

В проектах, которые я сделал, я использовал data-eval для хранения кода js в узле dom, а затем использовал его при рендеринге Statement (еще один «рак» JS, with теперь отключен в строгом режиме, рип...) для добавьте данные в цепочку областей видимости, а затем используйте eval для разбора и выполнения. Достигаемый эффект аналогичен этому:

<div data-eval="data.count = data.count + 1">
    {{data.count}}
</div>

Отрендеренный результат — это значение, вычисленное eval.

Многие библиотеки и фреймворки используют eval для реализации всевозможной черной магии. Ранний полезный eval парсинг json, такой как json2.js Дугласа Крокфорда (действительно ароматный!). Позже различные фреймворки MVVM также использовали новый Function, хороший друг eval, для реализации вычисления встроенных выражений шаблонов, таких как Vue и Avalon. Достигаемый эффект примерно такой же, как в примере, представленном автором выше, разница в том, что этим фреймворкам MVVM также необходимо сначала проанализировать шаблон и извлечь параметры новой функции на основе регулярных выражений.

Даже если вы не можете использовать eval, вы должны сделать его самостоятельно. Например, eval и new Function нельзя использовать в небольших программах, если вы хотите динамически внедрять и выполнять код, вам нужно пойти по большой кривой и самостоятельно реализовать парсер JS, основанный на принципе компиляции.

Суммировать

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


Ссылка на ссылку:

  1. Global eval. What are the options?
  2. Используют ли фреймворки MVVM, такие как Knockout, Vue и AvalonJS, eval или Function?
  3. eval() не зло, просто неправильно понято
  4. A new V8 is coming, Node.js performance is changing.
  5. V8: Behind the Scenes (February Edition feat. A tale of TurboFan)