分享好友 前端技术首页 频道列表

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

javascript  2023-03-08 21:150

一、定义

当客户不方便直接访问一个对象或者不满足需要的时候,提供一个对象来控制堆这个对象的访问。

二、举例

惰性单例模式的实现依靠缓存代理

三、结构

代理模式需要一个本体对象和一个代理对象。在代理模式下,对于本体对象的特定的操作通过代理对象进行。如图所示

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

 

 

   这种模式的关键点在于:本体对象和代理对象接口的一致性也就是说如果需要不通过代理进行操作,那么直接操作本体对象依然可以。

四、实现

代理模式分为很多类,其中经常用到的有保护代理、虚拟代理、缓存代理。

1.保护代理

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

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对应的图表的数据,这些数据都需要从后端请求。比如以某个省的地市经济统计情况为例,我们需要的页面如下:

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

可见这样的情况下,用户很可能不断地点击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("石家庄");

 五、总结

三种类型虽然均为代理模式,但是各自的目的并不相同,保护代理是为了阻止外部对内部对象的访问或者是操作等;虚拟代理是为了提升性能,延迟本体执行,在合适的时机进行触发,目的是减少本体的执行次数;缓存代理同样是为了提升性能,但是为了减缓内存的压力,同样的属性,在内存中只保留一份。

 

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

 

查看更多关于【javascript】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
JavaScript翻转字符串方法 js翻转一个字符串
先把字符串转化成数组String.prototype.split(),再借助数组的reverse方法翻转数组顺序(Array.prototype.reverse()),然后把数组转化成字符串。使用的API方法:String.prototype.split(' ')使用指定的分隔符字符串将一个String对象分割成字符串数组Array.prot

0评论2023-03-08951

javascript常见面试题之一:将字符串'get-element-by-id'转换成驼峰命名法;
var str='get-element-by-id'; function strToupper(str) { //利用split将字符串分割成数组var arr= str.split('-');for (var i = 1; iarr.length; i++) {      //1.利用for循环获取数组的每个元素,2.用charAt(0)获取每个元素的第一个字符;3.用substr

0评论2023-03-08971

javaScript的Date函数 javascript date(
1、获取当前时间  Date()获取到的时间是当前设备的显示的时间,开发中要考虑到用户的设备时间是否正确let nowTime = new Date(); // 获取当前时间  把data时间转换成常规格式scriptlet getTimeNow = () = {let nowTime = new Date(); // 获取当前时间——

0评论2023-03-08692

关于Javascript中通过实例对象修改原型对象属性值的问题
Javascript中的数据值有两大类:基本类型的数据值和引用类型的数据值。基本类型的数据值有5种:null、undefined、number、boolean和string。引用类型的数据值往大的说就1种,即Object类型。往细的说有:Object类型、Array类型、Date类型、Regexp类型、Functio

0评论2023-03-08388

javascript中defer的作用(转)
script src=".js.js" defer/scriptdefer的作用就是作用是文档加载完毕了再执行脚本,这样回避免找不到对象的问题 加上 defer 等于在页面完全在入后再执行,相当于 window.onload ,但应用上比 window.onload 更灵活! defer是脚本程序强大功能中的一个“无名英

0评论2023-03-08863

JavaScript中的arguments,callee,caller(转)
在提到上述的概念之前,首先想说说javascript中函数的隐含参数:argumentsArguments该对象代表正在执行的函数和调用它的函数的参数。[function.]arguments[n]参数function:选项。当前正在执行的 Function 对象的名字。 n :选项。要传递给 Function 对象的从

0评论2023-03-08862

前台javascript排序 js排序的几种方式
 script type="text/javascript"$(function () {$('.Sorthead-ShowUp').click(function () { var filed = $(this).attr("name"); $(".issorting").removeClass("issorting"); $(this).addClass("issorting"); D

0评论2023-03-08337

【Javascript】在文本框光标处插入文字并定位光标 (转)
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"html xmlns="http://www.w3.org/1999/xhtml"headmeta http-equiv="Content-Type" content="text/h

0评论2023-03-08683

javascript捕获页面窗口关闭事件
javascript捕获窗口关闭事件有两种方法 onbeforeunload()      ,onUnload()用法有两种:1.    function      window.onbeforeunload()      {      alert("关闭窗口")}           function      window.onunload() 

0评论2023-03-08834

javascript 伪数组和转化为标准数组
1: 什么是伪数组伪数组是一个含有length属性的json对象,它是按照索引的方式存储数据,它并不具有数组的一些方法,只能能通过Array.prototype.slice转换为真正的数组,并且带有length属性的对象。   var obj = {0:'a',1:'b',length:2}; // 伪数组var arr

0评论2023-03-08643

【javascript的那些事】等待加载完js后执行方法
很多时候,你也许会碰到使用的情景:js文件b.js还没有从服务器端加载到web端,而吧a.js中已经调用了b.js中的方法实例:这里是加载echart的时候碰到的具体实例引入js "js/echarts.common.min.js"需要调用  echarts 中的 init() ,如果没有加载好 echarts.com

0评论2023-03-08754

用Javascript做一个“获取验证码”的按钮
要求:①点击按钮后背景色会发生改变②有倒计时(一般为30秒) !DOCTYPE HTMLhtmlheadmeta charset="UTF-8" /titlepro.html/titlestyle type="text/css".checkCode {cursor: pointer;border: 1px solid black;text-align: center;line-height: 26px;width: 1

0评论2023-03-08834

JavaScript 输入内容就触发事件
textarea name="textarea" placeholder="请输入产品识别号" onkeyup="alert();"/textarea 

0评论2023-03-08411

JavaScript 在不刷新或跳转页面的情况下改变当前浏览器地址栏上的网址
JavaScript 在不刷新或跳转页面的情况下改变当前浏览器地址栏上的网址var stateObject = {};var title = "改变后的网址的标题";var newUrl = "/my/awesome/url";history.pushState(stateObject,title,newUrl); 

0评论2023-03-08996

JavaScript ----------------- 寄生式继承
寄生式继承  寄生式继承是于原型式继承紧密相关的一种思路。寄生式基础的思路与寄生构造函数和工厂模式类似,既创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。以下代码示范了寄生式继承模

0评论2023-03-08849

非入侵式JavaScript
非入侵式JavaScript针对哪些情况:  1.并不是每个人的浏览器都支持JavaScript。需要让每个人都能看到全部内容,并且无须在浏览器中执行代码   就能使用该应用。  2.一些运行方式非常奇怪的浏览器。比如视觉受损的人会使用屏幕阅读器,一些手机用户无法

0评论2023-03-08713

更多推荐