JavaScript 设计模式中的代理模式详解

前言:

代理模式,代理(proxy)是一个对象,它可以用来控制对另一个对象的访问。

现在页面上有一个香港回归最想听的金典曲目列表:

<ul id="container">
    <li>我的中国心</li>
    <li>东方之珠</li>
    <li>香港别来无恙</li>
    <li>偏偏喜欢你</li>
    <li>相亲相爱</li>
</ul>

需要给页面添加一个效果:每当用户点击列表中的项目时,都会弹出一条消息:我想听:${name},大致思路是给每个li元素添加一个点击事件。如下所示:

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>代理模式</title>
    </head>
    <body>
        <ul id="container">
            <li>我的中国心</li>
            <li>东方之珠</li>
            <li>香港别来无恙</li>
            <li>偏偏喜欢你</li>
            <li>相亲相爱</li>
        </ul>
        <script>
            const container = document.getElementById("container")

            Array.prototype.forEach.call(container.children, node => {
                node.addEventListener("click", function (e) {
                    e.preventDefault()
                    alert(`我想听: ${e.target.innerText}`)
                })
            })
        </script>
    </body>
</html>

这种方法可以满足要求,但这样做的缺点是性能开销,因为每个 li 标签都绑定到一个事件。如果列表中有数千个元素,是否绑定了数千个事件?

每个 li都有自己的事件处理机制,但不管是哪个li,其实都是ul的成员,这样可以将li的事件委托给父级节点 ul,让ul成为这些li的事件代理。

这样,只需要为这些li元素绑定一个事件,即为父级元素绑定一个事件。

const container = document.getElementById('container')

container.addEventListener('click', function (e) {
    if (e.target.nodeName === 'LI') {
        e.preventDefault()
        alert(`我想听: ${e.target.innerText}`)
    }
})

这就是代理模式的一种使用场合,代理模式是本体不直接出现,而是让代理间接解决问题。

  • 在上面代理模式的代码中,li并没有直接处理点击事件,而是将其委托给父级元素ul
  • 现实生活中,明星并不是直接出来谈生意,而是交给他们的经纪人,也就是明星的代理人。

代理模式的应用非常广泛,再来看另一个适用场景。假设有一个计算函数,参数是字符串,计算比较耗时。同时,这是一个纯函数,如果参数相同,则函数的返回值将相同。

function compute(str) {
    // 假设这个函数执行时间很长
    console.info("===> 超级计算开始了……");
    return `输入:${str}`;
}

现在需要给这个函数添加一个缓存函数:每次计算后,存储参数和对应的结果。在接下来的计算中,会先从缓存中查询计算结果。当然,可以直接修改这个函数的功能。但这并不好,因为缓存不是这个功能的固有特性。

说到缓存函数,在 《Javascript函数技巧学习》聊到其实现,其实现就是使用代理模式。

更好的解决方案是使用代理模式。

const cached = (fn) => {
    const cache = Object.create(null);
    return (str) => {
        const hit = cache[str];
        return hit || (cache[str] = fn(str));
    };
};
const cacheCompute = cached(compute);
console.log(cacheCompute("DevPoint"));
console.log(cacheCompute("DevPoint"));
console.log(cacheCompute("juejin"));

这样,就可以在不修改原函数逻辑的情况下为其扩展计算函数,这是代理模式的另一种使用场景,它允许向原始对象本身添加额外的功能,而无需更改它。

到此这篇关于JavaScript 设计模式中的代理模式详解的文章就介绍到这了,更多相关JS 代理模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解JavaScript系列(31):设计模式之代理模式详解

    介绍 代理,顾名思义就是帮助别人做事,GoF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 代理模式使得代理对象控制具体对象的引用.代理几乎可以是任何对象:文件,资源,内存中的对象,或者是一些难以复制的东西. 正文 我们来举一个简单的例子,假如dudu要送酸奶小妹玫瑰花,却不知道她的联系方式或者不好意思,想委托大叔去送这些玫瑰,那大叔就是个代理(其实挺好的,可以扣几朵给媳妇),那我们如何来做呢? 复制代码 代码如下: // 先声明美女对象 var

  • JavaScript设计模式之缓存代理模式原理与简单用法示例

    本文实例讲述了JavaScript设计模式之缓存代理模式原理与简单用法.分享给大家供大家参考,具体如下: 一.原理: 缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参数跟之前的一致,则可以直接返回前面存储的运算结果,提供效率以及节省开销. 二.实例: var mult = function(){ console.log('开始计算乘机'); var a = 1; for(var i = 0, l = arguments.length;i < l;i++){ a =

  • javascript设计模式之代理模式

    目录 一. 初识代理模式 二. 代理模式的实现思想 三. 代理模式分类 四. 虚拟代理模式的实际运用 五. 代理的使用意义及要求 六. 总结 一. 初识代理模式 代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问.它的用处就是当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.通俗来讲就是,代理是一个中间人,负责在客户和卖家之间传递信息,将没用的信息过滤,将有利于交易成功的信息传递给卖家,从而加大交易的成功率. 二. 代理模式的实现思想 现在我们

  • JavaScript的设计模式经典之代理模式

     一.代理模式概念 说明:顾名思义就是用一个类来代替另一个类来执行方法功能,这个模式跟装饰模式有点相似,不一样的是,代理模式是代替客户初始化被代理对象类,而装饰模式采用接口或初装饰者参数引用的方式来执行的. 解释:房屋中介,可以代理帮助卖家把房子卖给买家,这中间卖家说要卖的价钱就可以了,买家也可以提出自己要买的房型,中介可以帮忙处理中间环节.最后达成买卖.中介可以同时代理很多房屋买卖,并且可以代理租房事宜. 二.代理模式的作用和注意事项 模式作用: 1.远程代理(一个对象将不同空间的对象进行局部

  • 详解javascript设计模式三:代理模式

    代理模式是一种对程序对象进行控制性访问的一类解决方案. 引入代理模式,其实是为了实现单一职责的面向对象设计原则. 单一职责其实就是指在一个类中(js中通常指对象和函数等),应仅有一个引起它变化的原因.这样会帮助程序设计具有良好的健壮和高内聚特性,从而当变化发生时,程序设计会尽量少的受到意外破坏. 代理模式有多种方法,保护代理.远程代理.虚拟代理.缓存代理等. 但在javascript中,代理模式最常用到的两种方法是虚拟代理和缓存代理. 虚拟代理 在理解虚拟代理时,可以将其想象为一个经纪人,客户程

  • javascript设计模式 – 代理模式原理与用法实例分析

    本文实例讲述了javascript设计模式 – 代理模式原理与用法.分享给大家供大家参考,具体如下: 介绍:代理使我们很常见的一众模式,proxy,nginx都称之为代理,代理是什么意思呢?代理模式在客户端和目标对象之间加入一个新的代理对象,代理对象起到一个中介作用,去掉客户不能看到的内容和服务,或者增添客户需要的额外服务. 定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用.代理模式是一种对象结构型模式. 场景:我们还是以画图形为例,我将所有的绘图动作包装到Shape类中,使用代理

  • JavaScript设计模式之代理模式详解

    代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子.但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处.在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为. /** * pre:代理模式 * 小明追求A,B是A的好朋友,小明比较腼腆,不好意思直接将花交给A, * 于是小明将花交给B,再由B交给A. */ //----------- 示例1 --------- // 不使用代理

  • js设计模式之代理模式及订阅发布模式实例详解

    本文实例讲述了js设计模式之代理模式及订阅发布模式.分享给大家供大家参考,具体如下: 为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文章的第二篇文章,第一篇:. 1,代理模式,只是学习了虚拟代理以及缓存代理,具体案例 1)虚拟代理 //业务代码 var myImage = (function() { var imgNode = document.

  • JavaScript 设计模式中的代理模式详解

    前言: 代理模式,代理(proxy)是一个对象,它可以用来控制对另一个对象的访问. 现在页面上有一个香港回归最想听的金典曲目列表: <ul id="container"> <li>我的中国心</li> <li>东方之珠</li> <li>香港别来无恙</li> <li>偏偏喜欢你</li> <li>相亲相爱</li> </ul> 需要给页面添加

  • Java设计模式中的外观模式详解

    目录 模式介绍 UML类图 外观模式案例: 外观模式的注意事项和细节 模式介绍 外观模式(Facade) ,也叫“过程模式:外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节. UML类图 类图解析: Facade:为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象

  • JavaScript设计模式之职责链模式详解

    目录 职责链模式 1. 现实中的职责链模式 2. 实际开发中的职责链模式 3. 用职责链模式重构代码 4. 灵活可拆分的职责链节点 5. 异步的职责链 6. 职责链模式的优缺点 7. 用 AOP 实现职责链 8. 小结 职责链模式 职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 职责链模式的名字非常形象,一系列可能会处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到遇

  • JavaScript设计模式之中介者模式详解

    目录 中介者模式 现实中的中介者 中介者模式的例子 泡泡堂游戏 为游戏增加队伍 玩家增多带来的困扰 用中介者模式改造泡泡堂游戏 小结 中介者模式 在我们生活的世界中,每个人每个物体之间都会产生一些错综复杂的联系.在应用程序里也是一样,程序由大大小小的单一对象组成,所有这些对象都按照某种关系和规则来通信. 平时我们大概能记住 10 个朋友的电话.30 家餐馆的位置.在程序里,也许一个对象会和其他 10 个对象打交道,所以它会保持 10 个对象的引用.当程序的规模增大,对象会越来越多,它们之间的关系

  • Java设计模式中的门面模式详解

    目录 门面模式 概述 应用场景 目的 优缺点 主要角色 门面模式的基本使用 创建子系统角色 创建外观角色 客户端调用 门面模式实现商城下单 库存系统 支付系统 物流系统 入口系统 客户端调用 门面模式 概述 门面模式(Facade Pattern)又叫外观模式,属于结构性模式. 它提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口.使得子系统更容易使用. 客户端不需要知道系统内部的复杂联系,只需定义系统的入口.即在客户端和复杂系统之间再加一层,这一层

  • Java设计模式中责任链模式详解

    目录 1.责任链设计模式的定义 2.责任链设计模式的优点与不足 3.责任链设计模式的实现思路 4.责任链设计模式应用实例 5.责任链设计模式应用场景 编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观. 在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流程.请假流程等.公司员工请假,可批假的领导有部门负责人.副总经理.总经理等,但每个领导能批准的天数不同,员工必须根据需要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名.电话

  • Java中的代理模式详解及实例代码

    java 代理模式详解 前言: 在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为"代理"的第三者来实现间接引用.代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务. 简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能. 静态代理 所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编写代码的时候就已经把代理类的代码写好了,而动态代理则

  • Javascript设计模式之装饰者模式详解篇

    一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改变原对象的原本结构的情况下进行功能添加. 2. 装饰对象和原对象具有相同的接口,可以使客户以与原对象相同的方式使用装饰对象. 3. 装饰对象中包含原对象的引用,即装饰对象是真正的原对象经过包装后的对象. 二.Javascript装饰者模式详解: 描述: 装饰者模式中,可以在运行时动态添加附加功能到对

  • Java设计模式之代理模式详解

    一.代理模式 代理模式就是有一个张三,别人都没有办法找到他,只有他的秘书可以找到他.那其他人想和张三交互,只能通过他的秘书来进行转达交互.这个秘书就是代理者,他代理张三. 再看看另一个例子:卖房子 卖房子的步骤: 1.找买家 2.谈价钱 3.签合同 4.和房产局签订一些乱七八糟转让协议 一般卖家只在签合同的时候可能出面一下,其他的1,2,4都由中介去做.那你问这样有什么用呢? 首先,一个中介可以代理多个卖房子的卖家,其次,我们可以在不修改卖家的代码的情况下,给他实现房子加价.打广告等等夹带私货的

随机推荐