Angular.js: Jak działa $ eval i dlaczego różni się od vanilla eval?


151

Byłem ciekawy tego, $scope.$evalco tak często widzisz w dyrektywach, więc sprawdziłem źródło i znalazłem w rootScope.js:

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

$parsewydaje się być zdefiniowany przez program ParseProviderin parse.js, który wydaje się definiować jakąś własną mini-składnię (plik ma długość 900 linii).

Moje pytania to:

  1. Co dokładnie $evalrobi? Dlaczego potrzebuje własnego mini języka parsowania?

  2. Dlaczego nie evaljest używany zwykły stary JavaScript ?


13
$ eval oblicza wyrażenie kątowe względem / w bieżącym zakresie .
Mark Rajcok

4
BTW $parsejest niesamowicie świetny.
Fresheyeball

Odpowiedzi:


186

$evali $parsenie oceniaj JavaScript; oceniają wyrażenia AngularJS . Dołączona dokumentacja wyjaśnia różnice między wyrażeniami a JavaScript.

P: Co dokładnie robi $ eval? Dlaczego potrzebuje własnego mini języka parsowania?

Z dokumentów:

Wyrażenia to podobne do JavaScript fragmenty kodu, które są zwykle umieszczane w powiązaniach, takich jak {{wyrażenie}}. Wyrażenia są przetwarzane przez usługę $ parse.

Jest to mini-język podobny do JavaScript, który ogranicza to, co możesz uruchomić (np. Nie ma instrukcji przepływu sterowania, z wyjątkiem operatora trójskładnikowego), a także dodaje trochę dobroci AngularJS (np. Filtry).

P: Dlaczego nie jest używany zwykły stary javascript „eval”?

Ponieważ tak naprawdę nie ocenia JavaScript. Jak mówią doktorzy:

Jeśli ... chcesz uruchomić dowolny kod JavaScript, powinieneś uczynić go metodą kontrolera i wywołać metodę. Jeśli chcesz eval () wyrażenie kątowe z JavaScript, użyj metody $ eval ().

Dokumenty, do których linki znajdują się powyżej, zawierają dużo więcej informacji.


Powiedziałeś, że $ eval tak naprawdę nie ocenia JavaScript, ale jeśli zrobię $ eval ("{id: 'val'}"), otrzymam obiekt JS. (Angular 1.0.8)
Gabriel

7
@Yappli $evalnie ocenia JavaScript; ocenia wyrażenia AngularJS, które są trochę bezpieczniejszym podzbiorem JavaScript. "{id: 'val'}"jest prawidłowym wyrażeniem AngularJS i powinien zwrócić prawidłowy obiekt JS. Zobacz link powyżej, aby zobaczyć różnicę między wyrażeniami a zwykłym JS.
Josh David Miller

1
Dobra odpowiedź, ale nie jestem pewien, czy „np. Brak instrukcji kontroli przepływu” jest poprawne. Możesz zrobić coś takiego ... ng-click = "someVal? SomeFunc (someVal): noop", co jest doskonale poprawnym wyrażeniem kątowym
Charlie Martin

@CharlieMartin Dokumentacja wyraźnie mówi „brak instrukcji kontroli przepływu” , ale Twój punkt widzenia jest ważny. Jednak zdecydowanie nie polecałbym robienia tego w ngClick; ten rodzaj logiki prawie na pewno należy do kontrolera.
Josh David Miller

1
Ciekawe, że doktorzy mówią, że ponieważ wsparcie dla operatora trójskładnikowego zostało celowo dodane ... github.com/angular/angular.js/blob/master/src/ng/ ... ng-click był tylko prostym przykładem i zgadzam się ta logika powinna znajdować się w kontrolerze, ale nie widzę nic złego w używaniu operatora trójskładnikowego w notacji nawiasów, a zespół kątowy oczywiście też tego nie robi lub nie dodaliby do niego wsparcia. Przypuszczam, że gdyby trzeba było dokonać korekty, powinno to nastąpić w dokumentach przed tą odpowiedzią
Charlie Martin,

22

Z testu

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

Do wyrażenia oceny możemy również przekazać lokalne wartości.


2

Myślę, że na jedno z pierwotnych pytań tutaj nie udzielono odpowiedzi. Uważam, że vanilla eval () nie jest używana, ponieważ wtedy aplikacje kątowe nie działałyby jako aplikacje Chrome, co wyraźnie uniemożliwia użycie eval () ze względów bezpieczeństwa.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.