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() 方法,监控对数据的操作,从而可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。 

posted @ 2017-02-03 18:06  日月追影俯河山  阅读(196)  评论(0编辑  收藏  举报
TOP