脏治检查实现原理

1. 使用对象的watch/unwatch方法直接监控属性的变化

  1. Object.prototype.watch()

这个直接监控对象的属性变化,有变动直接调用对应的回调,很方便的样子,但是:

2. 新旧值对比

配置两个全局对象,一个对象保存之前的值,一个保存修改后的值,对比两个对象就能知道哪些属性发生了变化. 你可以定时循环检测,也可以在赋值操作上做点文章实现主动触发更新

3. 为属性配置属性设置器

  1. Object.defineProperty() - Object.defineProperty(obj, prop, descriptor)
  2. 解析 神奇的 Object.defineProperty

如果你懂java或者其他后端语言,一个属性可以有getter和setter,当修改一个属性的时候会调用setter,也就是主动的执行了一个方法。同样的在js中我们也可以这样实现。

var obj = {}
Object.defineProperty(obj, 'name', {
    set: function(val) {
        this._name = val;
        console.log('set name: ', this._name);
    },
    get: function() {
        console.log('get name');
        return this._name;
    }
})

obj.name = 'CooMark'
console.log(obj.name)

// set name:  CooMark
// get name
// CooMark

这样就不需要遍历所有的属性了,属性发生变化的时候会主动执行检查,帅爆了

descriptor对象属性简介

  1. value: 属性的值
  2. writable: 如果为false,属性的值就不能被重写,只能为只读了
  3. configurable: 总开关,一旦为false,就不能再设置他的(value,writable,configurable)
  4. enumerable: 是否能在for...in循环中遍历出来或在Object.keys中列举出来。
  5. get: 执行属性赋值的回调
  6. set: 执行属性取值时执行的回调

vuejs的实现

caryhgq Vue.js 有更好的性能,并且非常非常容易优化,因为它不使用脏检查。Angular,当 watcher 越来越多时会变得越来越慢,因为作用域内的每一次变化,所有 watcher 都要重新计算。并且,如果一些 watcher 触发另一个更新,脏检查循环(digest cycle)可能要运行多次。 Angular 用户常常要使用深奥的技术,以解决脏检查循环的问题。有时没有简单的办法来优化有大量 watcher 的作用域。Vue.js 则根本没有这个问题,因为它使用基于依赖追踪的观察系统并且异步列队更新,所有的数据变化都是独立地触发,除非它们之间有明确的依赖关系。唯一需要做的优化是在 v-for 上使用 track-by。

VueJS 数据驱动和依赖追踪分析

原文地址:https://www.cnblogs.com/wancy86/p/dirty_check.html