简述

观察者模式指的是一个目标对象被多个观察者对象监听,当目标对象监听的属性发生变化时,主动向观察者发送通知。

实现

ES5

ES5 可以通过Object.defineProperty来设置setget进行拦截来实现该模式。

代码

const observedObj = { _no: 1 }
const observerObj = { _no: 1 }

function observer(oldVal, newVal) {
  console.log(`observed的no属性值变为${newVal}`)
  observer._no = newVal
}

Object.defineProperty(observedObj, 'no', {
  set(newVal) {
    observer(this._no, newVal)
    this._no = newVal
  },
  get() {
    return this._no
  }
})

observedObj.no = 2
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj)
const observedObj = { _no: 1 }
const observerObj = { _no: 1 }

function observer(oldVal, newVal) {
  console.log(`observed的no属性值变为${newVal}`)
  observer._no = newVal
}

Object.defineProperty(observedObj, 'no', {
  set(newVal) {
    observer(this._no, newVal)
    this._no = newVal
  },
  get() {
    return this._no
  }
})

observedObj.no = 2
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj)

输出

observedObj的no属性值变为2
observedObj:  { _no: 2 }
observerObj:  { _no: 2 }
observedObj的no属性值变为2
observedObj:  { _no: 2 }
observerObj:  { _no: 2 }

ES6

使用 ES6 新特性 Proxy 和 Reflect 结合使用监听对象属性

代码

class Obj {
  constructor(no) {
    this.no = no
  }
}

const observedObj = new Obj(1)
const observerObj = new Obj(1)

const handler = {
  set(observed, key, value) {
    if (key === 'no') {
      observer(key, observed[key], value)
    }
    Reflect.set(observed, key, value)
  }
}

const observerProxy = new Proxy(observedObj, handler)

function observer(key, oldVal, newVal) {
  console.log(`observedObj的no属性值由${oldVal}变为${newVal}`)
  observerObj[key] = newVal
}

observerProxy.no = 2
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj)
class Obj {
  constructor(no) {
    this.no = no
  }
}

const observedObj = new Obj(1)
const observerObj = new Obj(1)

const handler = {
  set(observed, key, value) {
    if (key === 'no') {
      observer(key, observed[key], value)
    }
    Reflect.set(observed, key, value)
  }
}

const observerProxy = new Proxy(observedObj, handler)

function observer(key, oldVal, newVal) {
  console.log(`observedObj的no属性值由${oldVal}变为${newVal}`)
  observerObj[key] = newVal
}

observerProxy.no = 2
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj)

输出

observedObj的no属性值由1变为2
observedObj:  Obj { no: 2 }
observerObj:  Obj { no: 2 }
observedObj的no属性值由1变为2
observedObj:  Obj { no: 2 }
observerObj:  Obj { no: 2 }