Angular.js:$ eval如何工作?为什么它与vanilla eval不同?

Jon*_*nah 148 angularjs

我很好奇$scope.$eval你经常在指令中看到你,所以我查看了源代码,发现以下内容rootScope.js:

  $eval: function(expr, locals) {
    return $parse(expr)(this, locals);
  },
Run Code Online (Sandbox Code Playgroud)

$parse似乎是由ParseProviderin 定义的parse.js,它似乎定义了它自己的某种迷你语法(文件长900行).

我的问题是:

  1. 究竟在$eval做什么?为什么它需要自己的迷你解析语言?

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

Jos*_*ler 184

$eval并且$parse不评估JavaScript; 他们评估AngularJS 表达式.链接的文档解释了表达式和JavaScript之间的差异.

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

来自文档:

表达式是类似JavaScript的代码片段,通常放在绑定中,例如{{expression}}.表达式由$ parse服务处理.

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

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

因为它实际上并没有评估JavaScript.正如文档所说:

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

与上述相关的文档有更多信息.

  • @Yappli` $ eval`不评估JavaScript; 它评估AngularJS表达式,它有点像一个更安全的JavaScript子集.`"{id:'val'}"`是一个有效的AngularJS表达式,应该返回一个有效的JS对象.请参阅上面的链接,了解表达式和常规JS之间的区别. (6认同)

all*_*kim 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);
}));
Run Code Online (Sandbox Code Playgroud)

我们也可以传递本地的评估表达式.