Angular.js: Как работает $ eval и чем он отличается от vanilla eval?


151

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

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

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

Мои вопросы:

  1. Что именно $evalделает? Зачем ему нужен собственный мини-язык синтаксического анализа?

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


13
$ eval оценивает угловое выражение против / в текущей области .
Марк Райкок

4
Кстати $parse, безумно здорово.
Fresheyeball

Ответы:


186

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

Q: Что именно делает $ eval? Зачем ему нужен собственный мини-язык синтаксического анализа?

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

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

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

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

Потому что это на самом деле не оценка JavaScript. Как говорят в документах:

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

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


Вы сказали, что $ eval на самом деле не оценивает JavaScript, но если я сделаю $ eval ("{id: 'val'}"), я получу объект JS. (Angular 1.0.8)
Габриэль

7
@Yappli $evalне оценивает JavaScript; он оценивает выражения AngularJS, которые вроде как более безопасное подмножество JavaScript. "{id: 'val'}"является допустимым выражением AngularJS и должно возвращать действительный объект JS. См. Ссылку выше для различия между выражениями и обычным JS.
Джош Дэвид Миллер

1
Хороший ответ, но я не уверен, что «например, нет операторов потока управления» является точным. Вы можете сделать что-то вроде этого ... ng-click = "someVal? SomeFunc (someVal): noop", которое является совершенно допустимым угловым выражением
Чарли Мартин,

@CharlieMartin В документации конкретно говорится «нет операторов потока управления» , но ваша точка зрения верна. Однако я определенно не рекомендовал бы делать это в ngClick; такая логика почти наверняка принадлежит контроллеру.
Джош Дэвид Миллер

1
Интересно, что в документах говорится, что в качестве преднамеренно добавлена ​​поддержка троичного оператора ... github.com/angular/angular.js/blob/master/src/ng/… ng-click был всего лишь простым примером, и я согласен эта логика должна быть в контроллере, но я не вижу ничего плохого в использовании троичного оператора в скобочных обозначениях, и угловая команда, очевидно, тоже этого не делает, иначе они бы не добавили поддержку этого. Я полагаю, что если будет сделано исправление, то это должно произойти в документации до этого ответа
Чарли Мартин

22

Из теста,

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);
}));

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


2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.