Angular.js:$ eval如何工作,为什么与香草eval不同?


151

我很好奇$scope.$eval您经常在指令中看到您,因此我检查了源代码并在中找到以下内容rootScope.js

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

$parse似乎由ParseProviderin 定义,in parse.js似乎定义了自己的某种微型语法(文件长900行)。

我的问题是:

  1. 到底在$eval做什么?为什么需要自己的小型解析语言?

  2. 为什么不使用普通的旧JavaScript eval


13
$ eval 针对当前范围/在当前范围内评估Angular表达式。
Mark Rajcok

4
BTW $parse太棒了。
Fresheyeball 2013年

Answers:


186

$eval而且$parse不要评估JavaScript;他们评估AngularJS 表达式。链接的文档解释了表达式和JavaScript之间的区别。

问:$ eval到底在做什么?为什么需要自己的小型解析语言?

从文档:

表达式是类似于JavaScript的代码段,通常放置在诸如{{expression}}之类的绑定中。表达式由$ parse服务处理。

这是一种类似于JavaScript的迷你语言,它限制了您可以运行的内容(例如,除了三元运算符之外,没有控制流语句),并且增加了一些AngularJS的优点(例如,过滤器)。

问:为什么不使用普通的旧javascript“ eval”?

因为它实际上不是在评估JavaScript。正如文档所说:

如果您确实想运行任意JavaScript代码,则应将其设为控制器方法并调用该方法。如果要从JavaScript评估角度表达式,请使用$ eval()方法。

上面链接的文档有更多信息。


您说$ eval实际上没有评估JavaScript,但是如果我执行$ eval(“ {id:'val'}”),我得到一个JS对象。(角度1.0.8)
加百利

7
@Yappli $eval不评估JavaScript;它评估AngularJS表达式,有点像JavaScript的安全子集。"{id: 'val'}"是有效的AngularJS表达式,应返回有效的JS对象。有关表达式和常规JS之间的区别,请参见上面的链接。
乔什·大卫·米勒

1
好的答案,但我不确定“例如,没有控制流声明”是否正确。您可以执行以下操作... ng-click =“ someVal?someFunc(someVal):noop”,这是一个非常有效的角度表达式
Charlie Martin

@CharlieMartin该文档专门说“没有控制流语句”,但是您的观点是正确的。但是,我绝对不建议在ngClick中这样做;这种逻辑几乎可以肯定属于控制器。
乔什·大卫·米勒

1
有趣的是,文档说有意添加了对三元运算符的支持... github.com/angular/angular.js/blob/master/src/ng / ... ng-click只是一个简单的示例,我同意该逻辑应该在控制器中,但是在括号表示法中使用三元运算符不会出现任何错误,而且角度小组显然也没有,或者他们不会对此添加支持。我想如果要进行更正,则应在此答案之前的文档中进行
Charlie Martin

22

从测试来看

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

我们还可以通过本地人进行评估表达。


2

我认为这里的原始问题之一没有得到回答。我相信不使用香草eval(),因为角度应用程序将无法像Chrome应用程序一样工作,这出于安全原因明显阻止了eval()的使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.