Improve this doc

翻译者:@NigelYao

"表达式"是一种类似JavaScript的代码片段,通常在视图中以'{{ expression }}'的形式使用。表达式由$parse服务解析,而解析之后经常会使用过滤器来格式化成一种更加用户友好的形式。

例如,下面这些都是Angular中合法的表达式:

  • 1+2
  • user.name

Angular表达式与JS表达式

可能会有人认为Angular视图表达式就是JavaScript表达式,但这不完全正确,因为Angular并没有使用JavaScript中的'eval()'来解析表达式。你可以认为Angular表达式与JavaScript表达式有如下的区别:

  • 属性解析: 所有的属性的解析都是相对于作用域(scope)的,而不像JavaScript中的表达式解析那样是相对于全局'window'对象的。

  • 容错性: 表达式的解析对'undefined'和'null'具有容错性,这不像在JavaScript中,试图解析未定义的属性时会抛出ReferenceErrorTypeError错误.

  • 禁止控制流语句: 表达式中不允许包括下列语句:条件判断(if),循环(for/while),抛出异常(throw)。

另一方面,如果你想执行特定的JavaScript代码,你应该在一个控制器里导出一个方法,然后在模板中调用这个方法。如果你想在JavaScript中解析一个Angular表达式,使用$eval()方法。

例子

Source

  1.  
  1.  

Demo

你可以在此处试一试解析其他的表达式:

Source

  1.  
  1.  
  1.  

Demo

属性解析

属性解析发生在scope上。不像在JavaScript中,将默认的属性解析放在全局的window对象中,Angular表达式必须使用$window来指向全局的'window'对象。例如,如果你想调用在'window'上定义的'alert()'方法,在表达式中,你必须使用'$window.alert()'。作者故意这样设定,就是为了防止对全局状态非正常的访问(一些奇怪bug的常见来源)。

Source

  1.  
  1.  
  1.  

Demo

容错性

表达式的解析对undefined和null具有容错性。在JavaScript中,解析'a,b,c'时,如果'a'不是一个对象会抛出异常。在一些语言中这可能会有用,但表达式的解析在Angular中主要用在数据绑定上,我们会像下面这样使用表达式:

  1. {{a.b.c}}

此时如果'a'是未定义的(也许我们正等着服务器响应数据,在不久的将来其会被定义),解析抛出异常将不再合理。如果表达式不具有容错性的话,我们的代码会变的繁杂且影响阅读,例如:{{((a||{}).b||{}).c}}

类似的,在undefined和null的对象上调用方法'a.b.c()'时会返回undefined。

禁止控制流语句

在表达式中禁止写控制流语句。这背后的原因在于,Angular设计哲学的核心认为,应用逻辑应该在控制器中,而不是在视图中控制。如果你需要条件表达式,循环或者抛出异常出现在你的视图表达式中,请将其委托到JavaScript方法中执行。