javascript中的设计模式之代理模式

保护代理

保护代理的作用是当对本体对象的属性进行访问和赋值时,代理对象可以对其进行拦截。

在ES6中,代理是一个已经被实现的知识点,如下:

复制代码

var obj = {

    _name: "JYY",

    age: 29

};

var objProxy = new Proxy(obj, {

    get: function(target, key){

        if(key === "_name") return undefined;

        return target[key];

    },

    set: function(target, key){

        if(key === "_name") return;

    }

});

objProxy._name; // undefined

objProxy.age; // 29

复制代码

上面的代码中obj是本体对象,objProxy是代理对象,这个代理实现了禁止访问和设置内部私有属性的功能。在这段代码中,我们使用代理对象对本体对象的get和set方法进行了代理,本体对象和代理对象都包含了这个set和get接口(obj对象本身内部实现了get和set),所以如果我们绕过代理对象直接访问和赋值本体对象也是可以的:

复制代码

var obj = {

    _name: "JYY",

    age: 29

};

console.log(obj._name); //JYY

obj._name = "hah";

console.log(obj._name); // hah

复制代码

保护代理的重点在于,代理对象保护外界对于本体对象的可访问和可操作性,也就是说在保护代理中,代理对象是用于禁止外界对本体对象的操作,防止本体对象的属性被外界进行操作

2.虚拟代理

虚拟代理在我理解,就是用户认为已经执行了某个功能,事实上却时使用代理对象进行占位,待触发的时机到来,才会真正的执行本体对象的操作。也就是虚拟代理把一些开销很大的对象,延迟到真正需要他的时候才采取创建。因此虚拟代理的使用伴随的是性能的提升。

典型的虚拟代理的例子就是节流,如下所示:

复制代码

var resizeProxy = function(fn){

    let timer = null;

    return function(){

        if(!timer){

            timer = setTimeout(function(){

                fn && fn();

                timer = null;

            },1000)

        }

    }

};

var resizeChange = function(){

    console.log(1);

};

window.onresize = resizeProxy(resizeChange);

复制代码

这段代码是经典的使用节流控制窗体尺寸大小改变事件触发的例子,作用就是让resize事件的触发不那么频繁,自定义的控制触发的频率,这对于性能的提升很有帮助。

在这段代码里面,resizeChange就是本体,resizeProxy就是代理,如果不使用代理直接将fn复制给window.onresize依旧是可用的。而使用代理的作用就是首先进行占位,开发中代理内部的代码是不可见的(比如提供的是api),利用resizeProxy的不可见性,让客户认为已经调用了功能代码,但是事实上是我们并未立即执行代码,因为我们作为开发者知道立即执行会带来性能的丧失,只有在合适的时机我们才会委托代理执行本地代码,执行真正的业务代码。

3.缓存代理

缓存代理在单例模式中就已出现,用于创建惰性代理模式,其原理就是在需要时创建对象,并将该对象保存在闭包中,这样可以一次创建多次使用。

当然在惰性单例中使用是缓存代理最简单的实现方式。在实际开发中,我们可能会遇到这样的场景,在tab中每个tab页都包含多个图表,因此在点击tab的时候就需要获取这个tab对应的图表的数据,这些数据都需要从后端请求。比如以某个省的地市经济统计情况为例,我们需要的页面如下:

可见这样的情况下,用户很可能不断地点击tab切换城市,然后和其他城市进行对比。如果每次点击都请求数据,带给用户的体验会非常差。这样的情况下,我们就可以做个全局的缓存,当然你可以保存在组件的状态中,除此之外缓存代理也是个很棒的选择。代码如下:

复制代码

// 请求数据

function requestData(regionName){

    return new Promise(function(resolve, reject){

        var rest = ajax({

            type: "post",

            params: {regionName: regionName}

        })

        resolve(rest);

    })

}

// 初始化数据代理方法

var proxyInit = (function(){

    var cache = {};

    return async function(regionName){

        if(cache[regionName]){

            return cache[regionName];

        }else{

            return cache[regionName] = await requestData(regionName);

        }

    }

});

proxyInit("石家庄");


亚马逊测评 http://www.yisuping.com/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容