SOURCE

console 命令行工具 X clear

                    
>
console
$(function() {
  function observer(value, listeners) {
    // 只介绍原理,不处理array类型等细节处理了
    if (Object.prototype.toString.call(value) !== '[object Object]' || value.__observer__) {
      return;
    }
    value.__observer__ = true;
    var keys = Object.keys(value);
    for (let i = 0; i < keys.length; i++) {
      defineReactive(value, keys[i], value[keys[i]], listeners);
    }
  }

  function defineReactive(obj, key, val, listeners) {
    var listeners = listeners || {};
    var property = Object.getOwnPropertyDescriptor(obj, key);
    if (property && property.configurable === false) {
      return
    }
    var getter = property && property.get;
    var setter = property && property.set;
    // 子对象递归转换掉
    observer(val, listeners);
    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get: function() {
        const value = getter ? getter.call(obj) : val;
        listeners.getter && listeners.getter(obj, key, value);
        return value
      },
      set: function(newVal) {
        const value = getter ? getter.call(obj) : val
        if (newVal === value || (newVal !== newVal && value !== value)) {
          return
        }
        if (setter) {
          setter.call(obj, newVal)
        } else {
          val = newVal
        }
        observer(newVal, listeners);
        listeners.setter && listeners.setter(obj, key, value);
      }
    })
  }

  var $main = $('#main');
  var $getDate = $('#getCurDate');
  var obj = {
    curDate: new Date()
  };
  observer(obj, {
    getter: function(obj, key, value) {
      console.log('getter: ', obj, key, value);
    },
    setter: function(obj, key, value) {
      if(obj==obj && key == 'curDate') {
        $main.text(value.toLocaleString());
      }
      console.log('setter: ', obj, key, value);
    }
  })

  $getDate.on('click', function() {
    obj.curDate = new Date();
  })

})
<div id="main">
</div>
<br/>
<button id="getCurDate">
  获取当前日期
</button>