安全导航操作符 ( ?. ) 和空属性路径
Angular 的安全导航操作符 (?.
)是一种流畅而便利的方式,用来保护出现在属性路径中 null 和 undefined 值。 下例中,当currentHero
为空时,保护视图渲染器,让它免于失败。
The current hero's name is {{currentHero?.name}}
如果下列数据绑定中title
属性为空,会发生什么?
The title is {{title}}
这个视图仍然被渲染出来,但是显示的值是空;只能看到 “The title is”,它后面却没有任何东西。 这是合理的行为。至少应用没有崩溃。
假设模板表达式涉及属性路径,在下例中,显示一个空 (null) 英雄的firstName
。
The null hero's name is {{nullHero.name}}
JavaScript 抛出了空引用错误,Angular 也是如此:
TypeError: Cannot read property 'name' of null in[null].
晕,整个视图都不见了。
如果确信hero
属性永远不可能为空,可以声称这是合理的行为。 如果它必须不能为空,但它仍然是空值,实际上是制造了一个编程错误,它应该被捕获和修复。 这种情况应该抛出异常。
另一方面,属性路径中的空值可能会时常发生,特别是当我们知道数据最终会出现。
当等待数据的时候,视图渲染器不应该抱怨,而应该把这个空属性路径显示为空白,就像上面title
属性那样。
不幸的是,当currentHero
为空的时候,应用崩溃了。
<!--No hero,div not displayed,no error --> <div *ngIf="nullHero">The null hero's name is {{nullHero.name}}</div>
或者可以尝试通过&&
来把属性路径的各部分串起来,让它在遇到第一个空值的时候,就返回空。
The hero's name is {{nullHero && nullHero.name}}
这些方法都有价值,但是会显得笨重,特别是当这个属性路径非常长的时候。 想象一下在一个很长的属性路径(如a.b.c.d
)中对空值提供保护。
Angular 安全导航操作符 (?.
) 是在属性路径中保护空值的更加流畅、便利的方式。 表达式会在它遇到第一个空值的时候跳出。 显示是空的,但应用正常工作,而没有发生错误。
<!-- No hero,no problem! --> The null hero's name is {{nullHero?.name}}
在像a?.b?.c?.d
这样的长属性路径中,它工作得很完美。back to top
非空断言操作符(!)
在 TypeScript 2.0 中,我们可以使用--strictNullChecks
标志强制开启严格空值检查。TypeScript就会确保不存在意料之外的null或undefined。
在这种模式下,有类型的变量默认是不允许null或undefined值的,如果有未赋值的变量,或者试图把null或undefined赋值给不允许为空的变量,类型检查器就会抛出一个错误。
如果类型检查器在运行期间无法确定一个变量是null或undefined,那么它也会抛出一个错误。 我们自己可能知道它不会为空,但类型检查器不知道。 所以我们要告诉类型检查器,它不会为空,这时就要用到非空断言操作符。
Angular模板中的**非空断言操作符(!
)也是同样的用途。
例如,在用*ngIf来检查过hero
是已定义的之后,就可以断言hero
属性一定是已定义的。
"hero" The hero's name is {{hero!.name}} 在 Angular 编译器把你的模板转换成 TypeScript 代码时,这个操作符会防止 TypeScript 报告 "hero.name
可能为null或undefined"的错误。与安全导航操作符不同的是,非空断言操作符不会防止出现null或undefined。 它只是告诉 TypeScript 的类型检查器对特定的属性表达式,不做 "严格空值检测"。
如果我们打开了严格控制检测,那就要用到这个模板操作符,而其它情况下则是可选的。