Vue双向绑定的完成道理系列(二):设想形式

设想形式

1、装潢者形式

github源码

在不转变对象本身的基本上,在递次运转时期给对象动态的增加职责

//看一个简朴的例子:
Function.prototype.fn = function(fn){
    var self = this;
    return function(){
        self.apply(this,arguments);
        fn.apply(this,arguments);
    }
}

function a(){
    console.log('我是函数a');
}

var copyA = a.fn(function(){
    console.log('我是a函数分外的功用');
})

copyA();  
// 我是函数a
// 我是a函数分外的功用

//监听数组的变化
  var methods=['push','pop','shift','unshift','splice','slice','sort','reverse'];
    var Method = {};
    for(var i=0;i<methods.length;i++){
        var method = methods[i];
        (function(method){
            var original = Array.prototype[method];
            Method[method] = function(){
                console.log('监听数组的变化或许操纵函数等');
                return original.apply(this,arguments);
            }
        })(method)
    }
    var list = ['a','b','c'];
    list.__proto__ = Method;
    list.push('d');//打印:监听数组的变化或许操纵函数等

看一个段来自javascript面向对象编程指南(第二版)中关于装潢器形式的诠释及其代码:

    装潢器形式是一种组织型形式,它与对象的建立无关,主要斟酌的是怎样拓展对象的功用。也就是说,除了运用线性式(父-子-孙)继续体式格局以外,我们也可认为一个基本对象建立若干个装潢对象以拓展其功用。然后,由我们的递次自行挑选差别的装潢器,并按差别的递次运用它们。在差别的递次中我们可能会面对差别的需求,并从一样的装潢器鸠合中挑选差别的子集。
//装潢一颗圣诞树
    var tree = {};
    tree.decorate = function(){
        console.log('tree');
    }

    /*接着,再定义 getDecorator()要领,该要领用于增加分外的装潢器。装潢器被完成为组织器函数,都继续自 tree 对象。*/

    tree.getDecorator = function(deco){
        tree[deco].prototype = this;
        return new tree[deco];
    };
   
    /*下面来建立3个装潢器,我们将它设为 tree 的一个属性(以坚持全局定名空间的纯洁)。 以下对象也供应了 decorate()要领,注重它先调用了父类的decorate()要领。*/

    tree.Red = function(){
        this.decorate = function(){
            this.Red.prototype.decorate();
            // console.log(this.Red.prototype);
            // console.log(this.Red.prototype.decorate);
            console.log('red');
        };
        this.name = 'red';
    }
    tree.Blue = function(){
        this.decorate = function(){
            this.Blue.prototype.decorate();
            // console.log(this.Blue.prototype.decorate);
            //tree['Blue']的原型是tree,所以打印出"tree"
            console.log('blue');
        }
        this.name = 'blue';
    }
    tree.Angel = function(){
        this.decorate = function(){
            this.Angel.prototype.decorate();
            // console.log(this.Angel.prototype.decorate);
            console.log('angle');
        }
        this.name = 'angel';
    }

    /*把一切的装潢器都增加到基本对象中:*/

    tree = tree.getDecorator('Blue'); 
    tree = tree.getDecorator('Angel');
    tree = tree.getDecorator('Red');

    /*运转:*/
    tree.decorate();
    //tree
    //blue
    //angle
    //red

     /*剖析:
        1、实行tree = tree.getDecorator('Blue'):
            tree['Blue'].prototype = tree;
            tree = {decorate: ƒ, name: "blue"}
            即tree['Blue']赋值给tree,tree['Blue']的原型指向tree
        输出:
        "tree"
        "blue"

        2、实行tree = tree.getDecorator('Angel'):
            tree['Angel'].prototype = tree['Blue'],(这时候tree已赋值为tree['Blue'])
            tree = {decorate: ƒ, name: "Angle"}
            即tree['Angel']赋值给tree,tree['Angel']的原型指向tree['Blue']
        输出:
        "angel"

        3、实行tree = tree.getDecorator('Red'):
            tree['Red'].prototype = tree['Angel'],(这时候tree已赋值为tree['Angel'])
            tree = {decorate: ƒ, name: "Red"}
            即tree['Red']赋值给tree,tree['Red']的原型指向tree['Angel']
        输出:
        "red"
    */

/*
图解:从下往上顺次继续
  tree = {decorate:fn,getDecorator:fn}
                    |
     tree['Blue'].prototype//tree={decorate: ƒ, name: "blue"}
                                    |
                        tree['Angel'].prototype//tree={decorate: ƒ, name: "Angle"} 
                                                        |
                                                 tree['Red'].prototype//tree={decorate: ƒ, name: "Red"}     
*/                                                                                                  

2、观察者形式(偶然也称为宣布-定阅形式)

看一个段来自javascript面向对象编程指南(第二版)中关于装潢器形式的诠释及其代码:

观察者形式是一种行动型形式,主要用于处置惩罚差别对象
之间的交互通讯题目。观察者形式中通常会包括两类对象。

一个或多个宣布者对象:当有主要的事变发作时,会关照定阅者。

一个或多个定阅者对象:它们跟随一个或多个宣布者,监听它们的关照,并作出
响应的回响反映

var observer = {
        addSubscriber:function (callback){//增加定阅者
            if(typeof callback === "function"){
                this.subscribers[this.subscribers.length] = callback;
            }
        },
        removeSubscriber:function (callback){//删除定阅者
            for(var i=0;i<this.subscribers.length;i++){
                if(this.subscribers[i] === callback){
                    delete this.subscribers[i];
                }
            }
        },
        publish:function (what) {//授受并通报数据给定阅者
            for(var i=0;i<this.subscribers.length;i++){
                if(typeof this.subscribers[i] === "function"){
                    this.subscribers[i](what);
                }
            }
        },
        make:function(o){//将恣意对象转变成一个宣布者并为其增加上述要领。
            for(var i in this){//this->observer{addSubscriber: ƒ, removeSubscriber: ƒ, publish: ƒ, make:f}
                if(this.hasOwnProperty(i)){//observer.hasOwnProperty('addSubscriber') -> true
                    o[i] = this[i];
                    o.subscribers = [];
                }
            }//o-> {addSubscriber: ƒ, removeSubscriber: ƒ, publish: ƒ, make:f,subscribers:[],o.XX}
        }
    };

    //有个函数blogger和恣意一个函数jack
    var blogger = {
        writeBlogPost : function(){
            var content = 'blogger';
            this.publish(content);
        }
    };
    var jack = {
        read:function (what){
            console.log('jack定阅: '+what);
        }
    };

    //blogger变成宣布者
    observer.make(blogger);

    //jack定阅blogger
    blogger.addSubscriber(jack.read);

    //blogger宣布信息
    blogger.writeBlogPost();

    //输出:jack定阅: blogger

    末了: 别的函数也能够成为宣布者,
           blogger也能够增加恣意的函数为定阅者
           jack也能够定阅别的宣布者          
    以上总结为:
        1.指定一个宣布者
        2.给宣布者增加缓存列表,寄存回调函数,关照定阅者
        3.宣布信息时,宣布者遍历缓存表,触发寄存的回调函数
    下面看个简朴的例子:
  var Event = function(){
        this.subs = {};
    }

    //增加收听者:
    Event.prototype.addSubscriber=function(k,callback){
        if(!this.subs[k]){
            this.subs[k]=[];
        }
        this.subs[k].push(callback);
    };
    //宣布事宜:
    Event.prototype.publish=function(k,item){
        var fns=this.subs[k];

        if(fns){//防备宣布给不存在的对象
            for(var i=0;i<fns.length;i++){
                fns[i](item)
            }
        }

    }

    function reader(item){
        console.log(item);
        console.log('我是收听的');
        //console.log(arguments)
    }

    var event = new Event();
    event.addSubscriber('a',reader)
    event.addSubscriber('b',reader)
    event.publish('a','publish宣布信息');
    event.publish('b','publish宣布信息');//不存在的定阅事宜b

系列文章的目次:

Vue双向绑定的完成道理系列(一):Object.defineproperty
Vue双向绑定的完成道理系列(二):设想形式
Vue双向绑定的完成道理系列(三):监听器Observer和定阅者Watcher
Vue双向绑定的完成道理系列(四):补充指令剖析器compile

    原文作者:平平不平
    原文地址: https://segmentfault.com/a/1190000013051584
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞