两种技术的比较

本节将会概括性地指出脏检查和存取器技术的优缺点。

语法

脏检查不需要语法来定义的提供者和消费者,但是把 handler()(provider, property) 进行映射配对是笨拙和不灵活的。

存取器技术要求用 observable() 来封装提供者,但是自动 handler() 映射弥补了这个不足。对于使用数据绑定的大型项目来说,这是必须的功能。

性能

脏检查因为糟糕的性能问题而广受垢病。它不得不在每个摘要周期可能多次检查每个 (provider, property) -> handler 入口。而且,因为它无法知晓什么时候属性值发生变化,所以即便应用处于闲置状态也必须保持运转。

存取器速度更快,但是如果是监听一个很大的对象的话会不可避免地降低性能。使用存取器来替换提供者的每个属性经常会导致过度滥用。一个方案是在需要的时候动态构建存取器树而不是一开始就成批地创建。还有一种可替代的简单方案即是把不需要监听的属性用 noObserve() 函数封装起来,这个可以告诉 observable() 不要处理这些属性。令人沮丧的是,这会引入一些额外的语法。

灵活性

脏检查天生支持 expando(动态添加)和存取器属性。

存取器技术在这里有一个弱点。因为 Expando 属性不在初始的存取树上面,所以不支持存取器技术。举个栗子,这会导致数组问题,但是可以在添加了一个属性之后通过手动运行 observableProp() 来解决。因为存取器不能被存取器二次封装,所以存取属性是不支持的。通常的解决方法是使用 computed() 函数而不是 getter。这将引入更多的自定义语法。

定时选择

脏检查没有给我们太多选择的自由,因为我们不知道什么时候属性值真正发生了改变。handler() 函数只能通过不断地运行 digest() 循环来异步执行。

存取器技术创建的存取器是同步触发的,所以我们可以自由选择。可以选择马上运行 handler() ,或者将其保存在稍后异步执行的批处理中。前一种技术给予我们可预测性的优点,而后者可以通过移除重复项来提升性能。