JS当中的观察者模式
有时被称作发布/订阅模式,观察者模式
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式有效解决了复杂架构当中的耦合关系 , 使系统更加便于维护
在JS当中实现了观察者模式的前端框架很多 , 以VueJS为例
它使用的是Object.defineProperty()
方法 , 这个方法是在ES5当中加入的 , 所以不支持IE8以下浏览器
Object.defineProperty ( obj, prop, descriptor )
这个方法直接在一个对象上定义一个新属性 , 或者修改一个已经存在的属性 , 并返回这个对象
参数 :
- obj - 需要定义属性的对象
- prop - 需定义或修改的属性名称
- descriptor - 描述 , 可包含的键值如下
-
- configurable - 该属性的描述符可以被删除 , 默认false
- enumerable - 该属性可被枚举 , 例如在 for ( … in … ) 语句当中对属性执行遍历
- value - 该属性对应的值 , 默认undefined
- writable - 该属性是否可以被赋值运算符改变 , 默认为false
- get - 给属性提供getter方法 , 该方法返回值被用作属性值 , 默认undefined
- set - 给属性提供setter方法 , 该方法接受唯一参数 , 并将该参数作为新值分配给该属性 , 默认为undefined
var obj = {a:1,b:2}; Object.defineProperty(obj, "name", { configurable : true, enumerable : true, writable : false, value : "Sookie", }); obj.name = "abc"; console.log(obj.name); for(let key in obj) { console.log(`${key} = ${obj[key]}`); }
由于writable是false , 所以赋值的操作并没有生效 ( 在严格模式下该操作会报错 )
enumable是true , 所以该属性是可以被枚举的 , 在for循环遍历当中可以获得
运行结果如下
Sookie a = 1 b = 2 name = Sookie
getter与setter
var obj = {a:1,b:2}; Object.defineProperty(obj, "name", { configurable : true, enumerable : true, // writable : true, // value : "Sookie", //在指定get或set方法之后,就不能指定writable和value描述了 //否则会出现TypeError get : function() { console.log("getter方法执行"); return value; }, set : function(newValue) { console.log("setter方法执行"); value = newValue; } }); obj.name = "abc"; console.log(obj.name);
执行结果如下
setter方法执行 getter方法执行 abc
基于这个JS原生的方法 , 针对一个对象的属性变动进行监控的观察者模式就可以实现了
VueJS 使用Object.defineProperty() 方法,监控对数据的操作,从而可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。