AngularJS记住该值并将其与之前的值进行比较.这是基本的肮脏判断.如果值发生更改,则它会激发Change事件.
$apply()
方法是您从非AngularJS世界转换到AngularJS世界时调用的方法,它称为$digest()
.摘要只是一种普通的、老式的肮脏判断.它可以在所有浏览器上运行,并且完全可以预测.
对比脏判断(AngularJS)和更改侦听器(KnockoutJS和Backbone.js):虽然脏判断看起来很简单,甚至效率低下(我将在后面讨论),但事实证明它在语义上一直是正确的,而change Listener有很多奇怪的角落 case ,需要依赖项跟踪之类的东西来让它在语义上更加正确.KnockoutJS依赖项跟踪是解决AngularJS没有的问题的一个聪明功能.
Issues with change listeners:
- 语法很糟糕,因为浏览器本身并不支持它.是的,有代理,但它们并不是在所有情况下都是语义正确的,当然,在旧浏览器上也没有代理.底线是脏判断允许您执行POJO次判断,而KnockoutJS和Backbone.js强制您继承它们的类,并通过访问器访问您的数据.
- 改变合并.假设您有一个项目array.假设您想将项目添加到数组中,在循环添加时,每次添加都会触发更改事件,这会呈现UI.这对性能非常不利.你想要的是在最后只更新一次UI.更改事件的粒度太细.
- 更改侦听器会立即在setter上触发,这是一个问题,因为更改侦听器可以进一步更改数据,从而触发更多更改事件.这很糟糕,因为在堆栈上,可能会同时发生多个更改事件.假设你有两个数组,无论出于什么原因都需要保持同步.您只能添加一个或另一个,但每次添加都会触发一个更改事件,该事件现在对世界的看法不一致.这与线程锁定非常相似,JavaScript避免了线程锁定,因 for each 回调都以独占方式执行,直到完成.更改事件打破了这一点,因为setter可能会产生深远的后果,这些后果不是有意的,也不是显而易见的,这会再次造成线程问题.事实证明,您想要做的是延迟监听器的执行,并保证一次只运行一个监听器,因此任何代码都可以自由更改数据,并且它知道在这样做时没有其他代码运行.
What about performance?
因此,我们似乎很慢,因为肮脏的判断效率很低.这就是我们需要研究实数的地方,而不仅仅是理论上的论证,但首先让我们定义一些约束条件.
人类是:
So the real question is this: How many comparisons can you do on a browser in 50 ms? This is a hard question to answer as many factors come into play, but here is a test case: http://jsperf.com/angularjs-digest/6 which creates 10,000 watchers. On a modern browser this takes just under 6 ms. On Internet Explorer 8 it takes about 40 ms. As you can see, this is not an issue even on slow browsers these days. There is a caveat: The comparisons need to be simple to fit into the time limit... Unfortunately it is way too easy to add a slow comparison into AngularJS, so it is easy to build slow applications when you don't know what you are doing. But we hope to have an answer by providing an instrumentation module, which would show you which are the slow comparisons.
事实证明,视频游戏和GPU使用脏判断方法,特别是因为它是一致的.只要它们超过了监视器刷新率(通常为50-60赫兹,或每16.6-20毫秒一次),超过这一速度的任何性能都是浪费,因此你最好画更多的东西,而不是获得更高的FPS.