Почему строгий режим EcmaScript 5 идет на такую ​​большую длину, чтобы ограничить идентификатор `eval` - PullRequest
4 голосов
/ 19 декабря 2009

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

Ответы [ 2 ]

10 голосов
/ 25 декабря 2010

Бобинс в основном правильно. (Я работаю над SpiderMonkey, движком Mozilla JS, внедрил в него различные части ES5 и следую за обсуждениями ECMAScript, если позволяет время.) Вы (и разработчики, и читатели оба) действительно хотите, чтобы eval был каноническим eval, и Вы хотите, чтобы arguments был каноническим arguments. Используя строгий режим, вы можете получить это.

Но я укажу, что ограничения ES5 здесь не такие, как хотелось бы. Во-первых, и немного исправить бобинц, даже в строгом режиме, вы не можете быть уверены, eval - это оригинальная eval функция:

"use strict";
this.eval = function() { return "ohai"; };
eval("7 + 10"); // "ohai"

Это общеизвестная (среди поклонников JS) ошибка глобального объекта: сценарии используют глобальный объект, разделяемый между сценариями, именуемые и изменяемые, для разрешения имен. Если бы вы не могли ссылаться на объект, с которым связаны глобальные переменные, у вас не было бы этой проблемы. Вполне вероятно, что ES6 исправит это с помощью другой дополнительной системы (возможно, внеполосной, например, типа MIME, но пока неясно), которая всегда распространяется на все сценарии.

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

function outer()
{
  var eval = function() { return "kthxbai"; };
  function inner()
  {
    "use strict";
    return eval("2 + 5");
  }
  return inner();
}
outer(); // "kthxbai"

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

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

Стоит отметить, что все это не относится к arguments как поддельной специальной форме. Либо у вас есть строгий режим с помощью области действия функции, и в этом случае вы увидите , что функции arguments, а не arguments, назначенные во внешней области, или у вас есть глобальная функция область действия, в этом случае arguments не имеет специального поведения. (Зачем запрещать мутацию arguments в коде глобального строгого режима? Вероятно, простота, а также заставляет разработчиков повсеместно обращаться с ними как с более особой формой, но я не уверен.)

7 голосов
/ 19 декабря 2009

Я могу только строить догадки, но мне кажется, что ES5-строгий говорит, что eval и arguments должны рассматриваться как необработанный синтаксис, а не идентификаторы. Разумно, что эти две функции должны быть реализованы на синтаксическом уровне, потому что они имеют поведение Amazing Funky Magic, которое не может быть воспроизведено нормальной функцией.

(В частности, eval может записывать в локальные переменные в функции, которая вызывает ее, а запись в arguments странным образом изменяет значения локальных переменных, соответствующих аргументам. Хотя в строгом режиме это поведение, похоже, исчезает К счастью.)

Из соображений совместимости ES5 не может сделать синтаксические eval и arguments. Таким образом, они делают все возможное, то есть идентификатор arguments всегда относится к магии arguments, а идентификатор eval всегда исключительно к магии eval.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...