Angular.js: Wie funktioniert $ eval und warum unterscheidet es sich von Vanilla eval?


151

Ich war neugierig auf das, was $scope.$evalSie so oft in Direktiven sehen, also habe ich die Quelle überprüft und Folgendes gefunden in rootScope.js:

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

$parsescheint durch ParseProviderin definiert zu sein parse.js, was eine eigene Minisyntax zu definieren scheint (die Datei ist 900 Zeilen lang).

Meine Fragen sind:

  1. Was genau $evalmacht das? Warum braucht es eine eigene Mini-Parsing-Sprache?

  2. Warum wird kein einfaches altes JavaScript evalverwendet?


13
$ eval wertet einen Angular Ausdruck gegen / auf dem aktuellen Bereich .
Mark Rajcok

4
Übrigens $parseist wahnsinnig toll.
Fresheyeball

Antworten:


186

$evalund $parsekein JavaScript auswerten; Sie werten AngularJS- Ausdrücke aus . In der verknüpften Dokumentation werden die Unterschiede zwischen Ausdrücken und JavaScript erläutert.

F: Was genau macht $ eval? Warum braucht es eine eigene Mini-Parsing-Sprache?

Aus den Dokumenten:

Ausdrücke sind JavaScript-ähnliche Codefragmente, die normalerweise in Bindungen wie {{expression}} platziert werden. Ausdrücke werden vom $ parse-Dienst verarbeitet.

Es ist eine JavaScript-ähnliche Minisprache, die die Ausführung einschränkt (z. B. keine Kontrollflussanweisungen mit Ausnahme des ternären Operators) und einige AngularJS-Funktionen (z. B. Filter) hinzufügt.

F: Warum wird kein einfaches altes Javascript "eval" verwendet?

Weil es nicht wirklich JavaScript auswertet. Wie die Dokumente sagen:

Wenn ... Sie beliebigen JavaScript-Code ausführen möchten, sollten Sie ihn zu einer Controller-Methode machen und die Methode aufrufen. Wenn Sie einen Winkelausdruck aus JavaScript eval () möchten, verwenden Sie die Methode $ eval ().

Die oben verlinkten Dokumente enthalten viel mehr Informationen.


Sie sagten, $ eval wertet JavaScript nicht aus, aber wenn ich $ eval ("{id: 'val'}") mache, erhalte ich ein JS-Objekt. (Winkel 1.0.8)
Gabriel

7
@Yappli $evalwertet JavaScript nicht aus; Es wertet AngularJS-Ausdrücke aus, die einer sichereren Teilmenge von JavaScript ähneln. "{id: 'val'}"ist ein gültiger AngularJS-Ausdruck und sollte ein gültiges JS-Objekt zurückgeben. Siehe den obigen Link für den Unterschied zwischen Ausdrücken und regulärem JS.
Josh David Miller

1
Gute Antwort, aber ich bin mir nicht sicher, ob "zB keine Kontrollflussanweisungen" korrekt sind. Sie können so etwas tun ... ng-click = "someVal? SomeFunc (someVal): noop", was ein vollkommen gültiger Winkelausdruck ist
Charlie Martin

@CharlieMartin In der Dokumentation steht ausdrücklich "Keine Kontrollflussanweisungen" , aber Ihr Punkt ist gültig. Ich würde es jedoch definitiv nicht empfehlen, dies mit einem ngClick zu tun. Diese Art von Logik gehört mit ziemlicher Sicherheit in die Steuerung.
Josh David Miller

1
Interessant, dass die Dokumente sagen, dass die Unterstützung für den ternären Operator absichtlich hinzugefügt wurde ... github.com/angular/angular.js/blob/master/src/ng/… Der ng-Klick war nur ein einfaches Beispiel und ich stimme zu Diese Logik sollte sich in einem Controller befinden, aber ich sehe nichts Falsches daran, einen ternären Operator in der Klammer-Notation zu verwenden, und das Angular-Team tut dies offensichtlich auch nicht, oder sie hätten keine Unterstützung dafür hinzugefügt. Ich nehme an, wenn eine Korrektur vorgenommen werden sollte, sollte dies in den Dokumenten vor dieser Antwort geschehen
Charlie Martin

22

Aus dem Test,

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

Wir können auch Einheimische für den Bewertungsausdruck übergeben.


2

Ich denke, eine der ursprünglichen Fragen hier wurde nicht beantwortet. Ich glaube, dass vanilla eval () nicht verwendet wird, da dann eckige Apps nicht als Chrome-Apps funktionieren würden, was ausdrücklich verhindert, dass eval () aus Sicherheitsgründen verwendet wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.