Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js: How does $eval work and why is it different from vanilla eval?

Tags:

angularjs

I was curious about the $scope.$eval you so often see in directives, so I checked out the source and found the following in rootScope.js:

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

$parse appears to be defined by ParseProvider in parse.js, which appears to define some kind of mini-syntax of its own (the file is 900 lines long).

My questions are:

  1. What exactly is $eval doing? Why does it need its own mini parsing language?

  2. Why isn't plain old JavaScript eval being used?

like image 909
Jonah Avatar asked Sep 28 '22 00:09

Jonah


People also ask

What is $eval in AngularJS?

The AngularJS $eval method is used to executes the AngularJS expression on the current scope and returns the result. In AngularJS, expressions are similar to JavaScript code snippets that are usually placed in bindings such as {{ expression }}.

How does JavaScript eval work?

JavaScript eval() The eval() method evaluates or executes an argument. If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements.

Is eval slow JavaScript?

eval() is also slower than the alternatives, since it has to invoke the JavaScript interpreter, while many other constructs are optimized by modern JS engines. Additionally, modern JavaScript interpreters convert JavaScript to machine code. This means that any concept of variable naming gets obliterated.


3 Answers

$eval and $parse don't evaluate JavaScript; they evaluate AngularJS expressions. The linked documentation explains the differences between expressions and JavaScript.

Q: What exactly is $eval doing? Why does it need its own mini parsing language?

From the docs:

Expressions are JavaScript-like code snippets that are usually placed in bindings such as {{ expression }}. Expressions are processed by $parse service.

It's a JavaScript-like mini-language that limits what you can run (e.g. no control flow statements, excepting the ternary operator) as well as adds some AngularJS goodness (e.g. filters).

Q: Why isn't plain old javascript "eval" being used?

Because it's not actually evaluating JavaScript. As the docs say:

If ... you do want to run arbitrary JavaScript code, you should make it a controller method and call the method. If you want to eval() an angular expression from JavaScript, use the $eval() method.

The docs linked to above have a lot more information.

like image 187
Josh David Miller Avatar answered Oct 07 '22 10:10

Josh David Miller


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

We also can pass locals for evaluation expression.

like image 22
allenhwkim Avatar answered Oct 07 '22 08:10

allenhwkim


I think one of the original questions here was not answered. I believe that vanilla eval() is not used because then angular apps would not work as Chrome apps, which explicitly prevent eval() from being used for security reasons.

like image 2
Kevin MacDonald Avatar answered Oct 07 '22 10:10

Kevin MacDonald