Angular.js: How does $eval work and why is it different from vanilla eval?
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:
What exactly is
$eval
doing? Why does it need its own mini parsing language?Why isn't plain old JavaScript
eval
being used?
$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.
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.
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.