Angular.js: Як працює $ eval і чому він відрізняється від vanilla eval?


151

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

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

$parseСхоже, визначається ParseProviderв parse.js, який, як видається, визначає якийсь власний міні-синтаксис (файл - 900 рядків).

Мої запитання:

  1. Що саме $evalробить? Для чого потрібна власна мова для міні-розбору?

  2. Чому не використовується звичайний старий JavaScript eval?


13
$ eval оцінює кутовий вираз проти / на поточній області .
Марк Райкок

4
BTW $parseшалено чудово.
Fresheyeball

Відповіді:


186

$evalі $parseне оцінюйте JavaScript; вони оцінюють AngularJS вирази . Пов'язана документація пояснює відмінності між виразами та JavaScript.

З: Що саме робить $ eval? Для чого потрібна власна мова для міні-розбору?

З документів:

Вирази - це фрагменти кодового коду JavaScript, які зазвичай розміщуються у прив'язках, таких як {{express}}. Вирази обробляються сервісом $ parse.

Це міні-мова, схожа на JavaScript, що обмежує те, що ви можете запускати (наприклад, ніяких операцій управління потоком, за винятком потрійного оператора), а також додає користі AngularJS (наприклад, фільтри).

Питання: Чому не використовується звичайний старий JavaScript "eval"?

Тому що насправді це не JavaScript. Як кажуть документи:

Якщо ... ви хочете запустити довільний код JavaScript, вам слід зробити його методом контролера та викликати метод. Якщо ви хочете зрівняти кутове вираження з JavaScript, скористайтеся методом $ eval ().

Документи, зв'язані вище, мають набагато більше інформації.


Ви сказали, що $ eval насправді не оцінює JavaScript, але якщо я роблю $ eval ("{id: 'val'}"), я отримую об'єкт JS. (Кутова 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.