Angular.js: Как работает $eval и почему он отличается от ванильного eval?

Мне было интересно узнать о $scope.$eval, который вы так часто видите в директивах, поэтому я проверил источник и нашел следующее в rootScope.js:

  $eval: function(expr, locals) {
    return $parse(expr)(this, locals);
  },

$parse, по-видимому, определяется ParseProvider в parse.js, который, как представляется, определяет какой-то собственный мини-синтаксис (файл длиной 900 строк).

Мои вопросы:

  • Что именно делает $eval? Зачем нужен собственный мини-парсинг?

  • Почему не используется обычный старый JavaScript eval?

Ответ 1

$eval и $parse не оценивать JavaScript; они оценивают выражения AngularJS . Связанная документация объясняет различия между выражениями и JavaScript.

В: Что именно делает $eval? Зачем нужен собственный мини-парсинг?

Из документов:

Выражения - это фрагменты кода, подобные JavaScript, которые обычно помещаются в привязки, такие как {{expression}}. Выражения обрабатываются с помощью службы $parse.

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

В: Почему не используется простой старый javascript "eval"?

Потому что он фактически не оценивает JavaScript. Как говорят документы:

Если... вы хотите запустить произвольный код JavaScript, вы должны сделать его методом контроллера и вызвать метод. Если вы хотите eval() выражение angular из JavaScript, используйте метод $eval().

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

Ответ 2

Из теста

it('should allow passing locals to the expression', inject(function($rootScope) {
  expect($rootScope.$eval('a+1', {a: 2})).toBe(3);

  $rootScope.$eval(function(scope, locals) {
    scope.c = locals.b + 4;
  }, {b: 3});
  expect($rootScope.c).toBe(7);
}));

Мы также можем передавать locals для выражения оценки.

Ответ 3

Я думаю, что один из исходных вопросов здесь не ответил. Я считаю, что vanilla eval() не используется, потому что приложения angular не будут работать как приложения Chrome, которые явно запрещают использование eval() по соображениям безопасности.