什么是观察者模式
维基百科 https://zh.wikipedia.org/wiki/观察者模式 对观察者模式的定义如下:
观察者模式是软件设计模式的一种. 在此种模式中, 一个目标对象管理所有相依于它的观察者对象, 并且在它本身的状态改变时主动发出通知. 这通常透过呼叫各观察者所提供的方法来实现. 此种模式通常被用来实时事件处理系统.
说的简单些, 就是在数据发生改变时, 对应的处理函数自动执行. 维基的定义中涉及到了主动发出通知, 按照这种方式, 在 angularJS 中的事件广播更是中规中矩, 但是其缺点是代码的可维护性较差. 那么如果不进行主动通知, 而是在进行对象属性值设置时, 调用相关的处理函数, 也可达到同等效果. 如下见详细代码.
ES5 下的实现
在 ES5 中主要是通过
Object.defineProperty
方法定义对象属性的设置和获取, 并在进行设置时执行相关的处理函数, 代码示例如下:
- // 创建对象
- var targetObj = {
- age: 1
- }
- // 定义值改变时的处理函数
- function observer(oldVal, newVal) {
- // 其他处理逻辑...
- console.info('name 属性的值从' + oldVal + '改变为' + newVal);
- }
- // 定义 name 属性及其 set 和 get 方法
- Object.defineProperty(targetObj, 'name', {
- enumerable: true,
- configurable: true,
- get: function() {
- return name;
- },
- set: function(val) {
- // 调用处理函数
- observer(name, val) name = val;
- }
- });
- targetObj.name = 'Martin';
- targetObj.name = 'Lucas';
- console.info('targetObj:', targetObj)
输出结果为
...
name 属性的值从 Martin 改变为 Lucas
- targetObj: {age: 1, name: 'Lucas'}
- ...
ES6 的实现
使用 set 方法实现
- class TargetObj {
- constructor(age, name) {
- this.name = name;
- this.age = age;
- }
- set name(val) {
- observer(name, val);
- name = val;
- }
- }
- let targetObj = new TargetObj(1, 'Martin');
- // 定义值改变时的处理函数
- function observer(oldVal, newVal) {
- // 其他处理逻辑...
- console.info('name 属性的值从'+ oldVal +'改变为' + newVal);
- }
- targetObj.name = 'Lucas';
- console.info(targetObj)
输出结果为
...
name 属性的值从 Martin 改变为 Lucas
- targetObj: {age: 1, name: 'Lucas'}
- ...
使用 Reflect 和 Proxy 实现
在 ES6 中新增的 Proxy Api 用处很多, 结合 Reflect Api 可以方便的实现很多强大的逻辑, 详细介绍可以参见ECMAScript 6 入门-- 阮一峰 http://es6.ruanyifeng.com/#docs/reflect 中的介绍. 实现代码如下:
- class TargetObj {
- constructor(age, name) {
- this.name = name;
- this.age = age;
- }
- }
- let targetObj = new TargetObj(1, 'Martin');
- let observerProxy = new Proxy(targetObj, {
- set(target, property, value, reciever) {
- if (property === 'name') {
- observer(target[property], value);
- }
- Reflect.set(target, property, value, reciever);
- }
- });
- // 定义值改变时的处理函数
- function observer(oldVal, newVal) {
- // 其他处理逻辑...
- console.info(`name 属性的值从 ${oldVal} 改变为 ${newVal}`);
- }
- observerProxy.name = 'Lucas';
- console.info(targetObj);
输出结果为
...
name 属性的值从 Martin 改变为 Lucas
- targetObj: {age: 1, name: 'Lucas'}
- ...
总结
ES6 中很多的新增功能, 都有效的提升了 JS 本身的合理性和高效性
很多基础的方法, 概念, 虽然在做业务实现时使用较少, 但是去了解其理念, 对编码思想的影响是很大的
观察者模式可以很好的完成数据间的交互行为, 虽然已经经常在用, 但是具体了解后对整体的结构和原理有了更深层次的理解
Proxy 真的很好, 很强大
来源: https://juejin.im/entry/5ad06eb0518825482e394dd8