Angular.js: come funziona $ eval e perché è diverso da vanilla eval?


151

Ero curioso di $scope.$evalvederti così spesso nelle direttive, quindi ho controllato la fonte e ho trovato quanto segue in rootScope.js:

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

$parsesembra essere definito da ParseProviderin parse.js, che sembra definire una sorta di mini sintassi propria (il file è lungo 900 righe).

Le mie domande sono:

  1. Cosa sta $evalfacendo esattamente ? Perché ha bisogno del suo linguaggio di analisi mini?

  2. Perché non evalviene utilizzato il semplice vecchio JavaScript ?


13
$ eval valuta un'espressione angolare rispetto a / sull'ambito corrente .
Mark Rajcok,

4
BTW $parseè follemente fantastico.
Fresheyeball,

Risposte:


186

$evale $parsenon valutare JavaScript; valutano le espressioni di AngularJS . La documentazione collegata spiega le differenze tra espressioni e JavaScript.

Q: Cosa sta facendo esattamente $ eval? Perché ha bisogno del suo linguaggio di analisi mini?

Dai documenti:

Le espressioni sono snippet di codice simili a JavaScript che vengono generalmente inseriti in associazioni come {{espressione}}. Le espressioni vengono elaborate dal servizio $ parse.

È un mini-linguaggio simile a JavaScript che limita ciò che è possibile eseguire (ad es. Nessuna istruzione del flusso di controllo, ad eccezione dell'operatore ternario) e aggiunge un po 'di bontà di AngularJS (ad es. Filtri).

D: Perché non viene utilizzato semplicemente il vecchio javascript "eval"?

Perché in realtà non sta valutando JavaScript. Come dicono i documenti:

Se ... vuoi eseguire codice JavaScript arbitrario, dovresti renderlo un metodo controller e chiamare il metodo. Se si desidera eval () un'espressione angolare da JavaScript, utilizzare il metodo $ eval ().

I documenti collegati sopra hanno molte più informazioni.


Hai detto $ eval in realtà non sto valutando JavaScript ma se faccio $ eval ("{id: 'val'}") ottengo un oggetto JS. (Angolare 1.0.8)
Gabriel,

7
@Yappli $evalnon valuta JavaScript; valuta le espressioni di AngularJS, che sono un po 'come un sottoinsieme più sicuro di JavaScript. "{id: 'val'}"è un'espressione AngularJS valida e deve restituire un oggetto JS valido. Vedi il link sopra per la differenza tra espressioni e JS normale.
Josh David Miller,

1
Bella risposta ma non sono sicuro che "ad es. Nessuna dichiarazione del flusso di controllo" sia accurata. Puoi fare qualcosa del genere ... ng-click = "someVal? SomeFunc (someVal): noop" che è un'espressione angolare perfettamente valida
Charlie Martin

@CharlieMartin La documentazione dice specificamente "nessuna dichiarazione sul flusso di controllo" , ma il tuo punto è valido. Tuttavia, sicuramente non consiglierei di farlo in un ngClick; quel tipo di logica appartiene quasi certamente al controller.
Josh David Miller,

1
Interessante che i documenti affermino che il supporto per l'operatore ternario è stato aggiunto intenzionalmente ... github.com/angular/angular.js/blob/master/src/ng/… Il ng-click era solo un semplice esempio e sono d'accordo quella logica dovrebbe essere in un controller, ma non vedo nulla di male nell'usare un operatore ternario nella notazione parentesi e la squadra angolare ovviamente non lo fa o non avrebbero aggiunto supporto per questo. Suppongo che se dovesse essere fatta una correzione, dovrebbe accadere nei documenti prima di questa risposta
Charlie Martin

22

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

Possiamo anche passare i locali per l'espressione di valutazione.


2

Penso che una delle domande originali qui non abbia ricevuto risposta. Credo che vanilla eval () non venga utilizzato perché le app angolari non funzionerebbero come app di Chrome, il che impedisce esplicitamente l'utilizzo di eval () per motivi di sicurezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.